mirror of https://github.com/astral-sh/uv
Display path separators as backslashes on Windows (#11667)
Currently, `uv tool list --show-paths` will show backslashes as path separators for packages but not entrypoints. This PR changes this to be consistent. Closes #10426.
This commit is contained in:
parent
5f6529a69a
commit
88f0dfd03d
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
@ -6,7 +7,7 @@ use toml_edit::Table;
|
||||||
use toml_edit::Value;
|
use toml_edit::Value;
|
||||||
use toml_edit::{Array, Item};
|
use toml_edit::{Array, Item};
|
||||||
|
|
||||||
use uv_fs::PortablePath;
|
use uv_fs::{PortablePath, Simplified};
|
||||||
use uv_pypi_types::{Requirement, VerbatimParsedUrl};
|
use uv_pypi_types::{Requirement, VerbatimParsedUrl};
|
||||||
use uv_settings::ToolOptions;
|
use uv_settings::ToolOptions;
|
||||||
|
|
||||||
|
|
@ -98,6 +99,32 @@ pub struct ToolEntrypoint {
|
||||||
pub install_path: PathBuf,
|
pub install_path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for ToolEntrypoint {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{} ({})",
|
||||||
|
self.name,
|
||||||
|
self.install_path
|
||||||
|
.simplified_display()
|
||||||
|
.to_string()
|
||||||
|
.replace('/', "\\")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{} ({})",
|
||||||
|
self.name,
|
||||||
|
self.install_path.simplified_display()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Format an array so that each element is on its own line and has a trailing comma.
|
/// Format an array so that each element is on its own line and has a trailing comma.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
|
|
|
||||||
|
|
@ -98,12 +98,7 @@ pub(crate) async fn list(
|
||||||
// Output tool entrypoints
|
// Output tool entrypoints
|
||||||
for entrypoint in tool.entrypoints() {
|
for entrypoint in tool.entrypoints() {
|
||||||
if show_paths {
|
if show_paths {
|
||||||
writeln!(
|
writeln!(printer.stdout(), "- {}", entrypoint.to_string().cyan())?;
|
||||||
printer.stdout(),
|
|
||||||
"- {} ({})",
|
|
||||||
entrypoint.name,
|
|
||||||
entrypoint.install_path.simplified_display().cyan()
|
|
||||||
)?;
|
|
||||||
} else {
|
} else {
|
||||||
writeln!(printer.stdout(), "- {}", entrypoint.name)?;
|
writeln!(printer.stdout(), "- {}", entrypoint.name)?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,19 @@ impl TestContext {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a filter that ignores temporary directory in path.
|
||||||
|
pub fn with_filtered_windows_temp_dir(mut self) -> Self {
|
||||||
|
let pattern = regex::escape(
|
||||||
|
&self
|
||||||
|
.temp_dir
|
||||||
|
.simplified_display()
|
||||||
|
.to_string()
|
||||||
|
.replace('/', "\\"),
|
||||||
|
);
|
||||||
|
self.filters.push((pattern, "[TEMP_DIR]".to_string()));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Add extra directories and configuration for managed Python installations.
|
/// Add extra directories and configuration for managed Python installations.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_managed_python_dirs(mut self) -> Self {
|
pub fn with_managed_python_dirs(mut self) -> Self {
|
||||||
|
|
@ -267,6 +280,12 @@ impl TestContext {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clear filters on `TestContext`.
|
||||||
|
pub fn clear_filters(mut self) -> Self {
|
||||||
|
self.filters.clear();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Discover the path to the XDG state directory. We use this, rather than the OS-specific
|
/// Discover the path to the XDG state directory. We use this, rather than the OS-specific
|
||||||
/// temporary directory, because on macOS (and Windows on GitHub Actions), they involve
|
/// temporary directory, because on macOS (and Windows on GitHub Actions), they involve
|
||||||
/// symlinks. (On macOS, the temporary directory is, like `/var/...`, which resolves to
|
/// symlinks. (On macOS, the temporary directory is, like `/var/...`, which resolves to
|
||||||
|
|
@ -988,6 +1007,14 @@ impl TestContext {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Only the filters added to this test context.
|
||||||
|
pub fn filters_without_standard_filters(&self) -> Vec<(&str, &str)> {
|
||||||
|
self.filters
|
||||||
|
.iter()
|
||||||
|
.map(|(p, r)| (p.as_str(), r.as_str()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// For when we add pypy to the test suite.
|
/// For when we add pypy to the test suite.
|
||||||
#[allow(clippy::unused_self)]
|
#[allow(clippy::unused_self)]
|
||||||
pub fn python_kind(&self) -> &'static str {
|
pub fn python_kind(&self) -> &'static str {
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,38 @@ fn tool_list_paths() {
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[test]
|
||||||
|
fn tool_list_paths_windows() {
|
||||||
|
let context = TestContext::new("3.12")
|
||||||
|
.clear_filters()
|
||||||
|
.with_filtered_windows_temp_dir();
|
||||||
|
let tool_dir = context.temp_dir.child("tools");
|
||||||
|
let bin_dir = context.temp_dir.child("bin");
|
||||||
|
|
||||||
|
// Install `black`
|
||||||
|
context
|
||||||
|
.tool_install()
|
||||||
|
.arg("black==24.2.0")
|
||||||
|
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
|
||||||
|
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str())
|
||||||
|
.assert()
|
||||||
|
.success();
|
||||||
|
|
||||||
|
uv_snapshot!(context.filters_without_standard_filters(), context.tool_list().arg("--show-paths")
|
||||||
|
.env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str())
|
||||||
|
.env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
black v24.2.0 ([TEMP_DIR]\tools\black)
|
||||||
|
- black.exe ([TEMP_DIR]\bin\black.exe)
|
||||||
|
- blackd.exe ([TEMP_DIR]\bin\blackd.exe)
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tool_list_empty() {
|
fn tool_list_empty() {
|
||||||
let context = TestContext::new("3.12").with_filtered_exe_suffix();
|
let context = TestContext::new("3.12").with_filtered_exe_suffix();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue