Skip to content

Commit

Permalink
Merge branch 'main' into build-all
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Sep 27, 2024
2 parents ee88c95 + ed1684a commit 5bcac4c
Show file tree
Hide file tree
Showing 18 changed files with 225 additions and 87 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/build-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,7 @@ jobs:
# Generate Dockerfile content
cat <<EOF > Dockerfile
FROM ${BASE_IMAGE}
COPY --from=${{ env.UV_BASE_IMG }}:latest /uv /usr/local/bin/uv
COPY --from=${{ env.UV_BASE_IMG }}:latest /uvx /usr/local/bin/uvx
COPY --from=${{ env.UV_BASE_IMG }}:latest /uv /uvx /usr/local/bin/
ENTRYPOINT []
CMD ["/usr/local/bin/uv"]
EOF
Expand Down
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ RUN cp target/$(cat rust_target.txt)/release/uv /uv \
# RUN strip --strip-all /uv

FROM scratch
COPY --from=build /uv /uv
COPY --from=build /uvx /uvx
COPY --from=build /uv /uvx /
WORKDIR /io
ENTRYPOINT ["/uv"]
7 changes: 7 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2038,6 +2038,13 @@ pub struct BuildArgs {
#[arg(long)]
pub wheel: bool,

#[arg(long, overrides_with("no_build_logs"), hide = true)]
pub build_logs: bool,

/// Hide logs from the build backend.
#[arg(long, overrides_with("build_logs"), hide = true)]
pub no_build_logs: bool,

/// Constrain build dependencies using the given requirements files when building
/// distributions.
///
Expand Down
3 changes: 2 additions & 1 deletion crates/uv-python/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,8 @@ impl InterpreterInfo {
tempdir.path().escape_for_python()
);
let output = Command::new(interpreter)
.arg("-I")
.arg("-I") // Isolated mode.
.arg("-B") // Don't write bytecode.
.arg("-c")
.arg(script)
.output()
Expand Down
22 changes: 2 additions & 20 deletions crates/uv-resolver/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,6 @@ pub enum ResolveError {
#[error("Attempted to wait on an unregistered task: `{_0}`")]
UnregisteredTask(String),

#[error("Package metadata name `{metadata}` does not match given name `{given}`")]
NameMismatch {
given: PackageName,
metadata: PackageName,
},

#[error(transparent)]
PubGrubSpecifier(#[from] PubGrubSpecifierError),

Expand All @@ -61,9 +55,6 @@ pub enum ResolveError {
#[error("Package `{0}` attempted to resolve via URL: {1}. URL dependencies must be expressed as direct requirements or constraints. Consider adding `{0} @ {1}` to your dependencies or constraints file.")]
DisallowedUrl(PackageName, String),

#[error("There are conflicting editable requirements for package `{0}`:\n- {1}\n- {2}")]
ConflictingEditables(PackageName, String, String),

#[error(transparent)]
DistributionType(#[from] distribution_types::Error),

Expand All @@ -89,14 +80,6 @@ pub enum ResolveError {
#[error(transparent)]
NoSolution(#[from] NoSolutionError),

#[error("{package} {version} depends on itself")]
SelfDependency {
/// Package whose dependencies we want.
package: Box<PubGrubPackage>,
/// Version of the package for which we want the dependencies.
version: Box<Version>,
},

#[error("Attempted to construct an invalid version specifier")]
InvalidVersion(#[from] pep440_rs::VersionSpecifierBuildError),

Expand All @@ -106,9 +89,8 @@ pub enum ResolveError {
#[error("found conflicting distribution in resolution: {0}")]
ConflictingDistribution(ConflictingDistributionError),

/// Something unexpected happened.
#[error("{0}")]
Failure(String),
#[error("Package `{0}` is unavailable")]
PackageUnavailable(PackageName),
}

impl<T> From<tokio::sync::mpsc::error::SendError<T>> for ResolveError {
Expand Down
8 changes: 4 additions & 4 deletions crates/uv-resolver/src/pubgrub/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::python_requirement::PythonRequirement;

/// [`Arc`] wrapper around [`PubGrubPackageInner`] to make cloning (inside PubGrub) cheap.
#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct PubGrubPackage(Arc<PubGrubPackageInner>);
pub(crate) struct PubGrubPackage(Arc<PubGrubPackageInner>);

impl Deref for PubGrubPackage {
type Target = PubGrubPackageInner;
Expand Down Expand Up @@ -38,7 +38,7 @@ impl From<PubGrubPackageInner> for PubGrubPackage {
/// package (e.g., `black[colorama]`), and mark it as a dependency of the real package (e.g.,
/// `black`). We then discard the virtual packages at the end of the resolution process.
#[derive(Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum PubGrubPackageInner {
pub(crate) enum PubGrubPackageInner {
/// The root package, which is used to start the resolution process.
Root(Option<PackageName>),
/// A Python version.
Expand Down Expand Up @@ -167,7 +167,7 @@ impl PubGrubPackage {
}

/// Returns `true` if this PubGrub package is a proxy package.
pub fn is_proxy(&self) -> bool {
pub(crate) fn is_proxy(&self) -> bool {
matches!(
&**self,
PubGrubPackageInner::Extra { .. }
Expand Down Expand Up @@ -219,7 +219,7 @@ impl PubGrubPackage {
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Hash, Ord)]
pub enum PubGrubPython {
pub(crate) enum PubGrubPython {
/// The Python version installed in the current environment.
Installed,
/// The Python version for which dependencies are being resolved.
Expand Down
4 changes: 1 addition & 3 deletions crates/uv-resolver/src/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1216,9 +1216,7 @@ impl<InstalledPackages: InstalledPackagesProvider> ResolverState<InstalledPackag
false,
"Dependencies were requested for a package that is not available"
);
return Err(ResolveError::Failure(format!(
"The package is unavailable: {name}"
)));
return Err(ResolveError::PackageUnavailable(name.clone()));
}

// Wait for the metadata to be available.
Expand Down
33 changes: 18 additions & 15 deletions crates/uv-workspace/src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -637,11 +637,12 @@ impl Workspace {

// Add all other workspace members.
for member_glob in workspace_definition.clone().members.unwrap_or_default() {
let absolute_glob = workspace_root
.simplified()
.join(member_glob.as_str())
.to_string_lossy()
.to_string();
let absolute_glob = PathBuf::from(glob::Pattern::escape(
workspace_root.simplified().to_string_lossy().as_ref(),
))
.join(member_glob.as_str())
.to_string_lossy()
.to_string();
for member_root in glob(&absolute_glob)
.map_err(|err| WorkspaceError::Pattern(absolute_glob.to_string(), err))?
{
Expand Down Expand Up @@ -1284,11 +1285,12 @@ fn is_excluded_from_workspace(
workspace: &ToolUvWorkspace,
) -> Result<bool, WorkspaceError> {
for exclude_glob in workspace.exclude.iter().flatten() {
let absolute_glob = workspace_root
.simplified()
.join(exclude_glob.as_str())
.to_string_lossy()
.to_string();
let absolute_glob = PathBuf::from(glob::Pattern::escape(
workspace_root.simplified().to_string_lossy().as_ref(),
))
.join(exclude_glob.as_str())
.to_string_lossy()
.to_string();
for excluded_root in glob(&absolute_glob)
.map_err(|err| WorkspaceError::Pattern(absolute_glob.to_string(), err))?
{
Expand All @@ -1309,11 +1311,12 @@ fn is_included_in_workspace(
workspace: &ToolUvWorkspace,
) -> Result<bool, WorkspaceError> {
for member_glob in workspace.members.iter().flatten() {
let absolute_glob = workspace_root
.simplified()
.join(member_glob.as_str())
.to_string_lossy()
.to_string();
let absolute_glob = PathBuf::from(glob::Pattern::escape(
workspace_root.simplified().to_string_lossy().as_ref(),
))
.join(member_glob.as_str())
.to_string_lossy()
.to_string();
for member_root in glob(&absolute_glob)
.map_err(|err| WorkspaceError::Pattern(absolute_glob.to_string(), err))?
{
Expand Down
11 changes: 10 additions & 1 deletion crates/uv/src/commands/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub(crate) async fn build(
output_dir: Option<PathBuf>,
sdist: bool,
wheel: bool,
build_logs: bool,
build_constraints: Vec<RequirementsSource>,
hash_checking: Option<HashCheckingMode>,
python: Option<String>,
Expand All @@ -65,6 +66,7 @@ pub(crate) async fn build(
output_dir.as_deref(),
sdist,
wheel,
build_logs,
&build_constraints,
hash_checking,
python.as_deref(),
Expand Down Expand Up @@ -138,6 +140,7 @@ async fn build_impl(
output_dir: Option<&Path>,
sdist: bool,
wheel: bool,
build_logs: bool,
build_constraints: &[RequirementsSource],
hash_checking: Option<HashCheckingMode>,
python_request: Option<&str>,
Expand Down Expand Up @@ -487,7 +490,13 @@ async fn build_package(
let dist = None;

let build_output = match printer {
Printer::Default | Printer::NoProgress | Printer::Verbose => BuildOutput::Stderr,
Printer::Default | Printer::NoProgress | Printer::Verbose => {
if build_logs {
BuildOutput::Stderr
} else {
BuildOutput::Quiet
}
}
Printer::Quiet => BuildOutput::Quiet,
};

Expand Down
83 changes: 78 additions & 5 deletions crates/uv/src/commands/tool/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@ use crate::commands::pip::operations;
use crate::commands::project::{resolve_names, EnvironmentSpecification, ProjectError};
use crate::commands::reporters::PythonDownloadReporter;
use crate::commands::tool::Target;
use crate::commands::{
project::environment::CachedEnvironment, tool::common::matching_packages, tool_list,
};
use crate::commands::{project::environment::CachedEnvironment, tool::common::matching_packages};
use crate::commands::{ExitStatus, SharedState};
use crate::printer::Printer;
use crate::settings::ResolverInstallerSettings;
Expand Down Expand Up @@ -79,9 +77,13 @@ pub(crate) async fn run(
cache: Cache,
printer: Printer,
) -> anyhow::Result<ExitStatus> {
// treat empty command as `uv tool list`
// Treat empty command similar to `uv tool list`, list available tools.
let Some(command) = command else {
return tool_list(false, false, &cache, printer).await;
match list_available_tools(invocation_source, &cache, printer).await {
// It is a failure because user misses a required tool name.
Ok(()) => return Ok(ExitStatus::Error),
Err(err) => return Err(err),
};
};

let (target, args) = command.split();
Expand Down Expand Up @@ -262,6 +264,77 @@ fn get_entrypoints(
)?)
}

/// Display a list of tools that provide the executable.
///
/// If there is no package providing the executable, we will display a message to how to install a package.
async fn list_available_tools(
invocation_source: ToolRunCommand,
cache: &Cache,
printer: Printer,
) -> anyhow::Result<()> {
writeln!(
printer.stdout(),
"Provide a command to invoke with `{invocation_source} <command>` \
or `{invocation_source} --from <package> <command>`.\n"
)?;

let installed_tools = InstalledTools::from_settings()?;
let no_tools_installed_msg =
"No tools installed. See `uv tool install --help` for more information.";
let _lock = match installed_tools.lock().await {
Ok(lock) => lock,
Err(uv_tool::Error::Io(err)) if err.kind() == std::io::ErrorKind::NotFound => {
writeln!(printer.stdout(), "{no_tools_installed_msg}")?;
return Ok(());
}
Err(err) => return Err(err.into()),
};

let mut tools = installed_tools.tools()?.into_iter().collect::<Vec<_>>();
tools.sort_by_key(|(name, _)| name.clone());

if tools.is_empty() {
writeln!(printer.stdout(), "{no_tools_installed_msg}")?;
return Ok(());
}

let mut buf = String::new();
for (name, tool) in tools {
// Skip invalid tools.
let Ok(tool) = tool else {
continue;
};

// Output tool name and version.
let Ok(version) = installed_tools.version(&name, cache) else {
continue;
};
writeln!(buf, "{}", format!("{name} v{version}").bold())?;

// Output tool entrypoints.
for entrypoint in tool.entrypoints() {
writeln!(buf, "- {}", entrypoint.name)?;
}
}

// Installed tools were malformed or failed fetching versions.
if buf.is_empty() {
writeln!(printer.stderr(), "{no_tools_installed_msg}")?;
return Ok(());
}

writeln!(
printer.stdout(),
"The following tools are already installed:\n"
)?;
writeln!(printer.stdout(), "{buf}")?;
writeln!(
printer.stdout(),
"See `{invocation_source} --help` for more information."
)?;
Ok(())
}

/// Display a warning if an executable is not provided by package.
///
/// If found in a dependency of the requested package instead of the requested package itself, we will hint to use that instead.
Expand Down
1 change: 1 addition & 0 deletions crates/uv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,7 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
args.out_dir,
args.sdist,
args.wheel,
args.build_logs,
build_constraints,
args.hash_checking,
args.python,
Expand Down
4 changes: 4 additions & 0 deletions crates/uv/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1675,6 +1675,7 @@ pub(crate) struct BuildSettings {
pub(crate) out_dir: Option<PathBuf>,
pub(crate) sdist: bool,
pub(crate) wheel: bool,
pub(crate) build_logs: bool,
pub(crate) build_constraint: Vec<PathBuf>,
pub(crate) hash_checking: Option<HashCheckingMode>,
pub(crate) python: Option<String>,
Expand All @@ -1697,6 +1698,8 @@ impl BuildSettings {
no_require_hashes,
verify_hashes,
no_verify_hashes,
build_logs,
no_build_logs,
python,
build,
refresh,
Expand All @@ -1710,6 +1713,7 @@ impl BuildSettings {
out_dir,
sdist,
wheel,
build_logs: flag(build_logs, no_build_logs).unwrap_or(true),
build_constraint: build_constraint
.into_iter()
.filter_map(Maybe::into_option)
Expand Down
Loading

0 comments on commit 5bcac4c

Please sign in to comment.