mirror of https://github.com/astral-sh/uv
Merge branch 'zb/extra-build-dependencies' into zb/flash-attn
This commit is contained in:
commit
1c52d9ad35
|
|
@ -5538,6 +5538,7 @@ dependencies = [
|
||||||
"tracing-test",
|
"tracing-test",
|
||||||
"unicode-width 0.2.1",
|
"unicode-width 0.2.1",
|
||||||
"url",
|
"url",
|
||||||
|
"uv-cache-key",
|
||||||
"uv-fs",
|
"uv-fs",
|
||||||
"uv-normalize",
|
"uv-normalize",
|
||||||
"uv-pep440",
|
"uv-pep440",
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,9 @@ mod resolver {
|
||||||
universal: bool,
|
universal: bool,
|
||||||
) -> Result<ResolverOutput> {
|
) -> Result<ResolverOutput> {
|
||||||
let build_isolation = BuildIsolation::default();
|
let build_isolation = BuildIsolation::default();
|
||||||
|
let extra_build_requires = uv_distribution::ExtraBuildRequires {
|
||||||
|
extra_build_dependencies: uv_workspace::pyproject::ExtraBuildDependencies::default(),
|
||||||
|
};
|
||||||
let build_options = BuildOptions::default();
|
let build_options = BuildOptions::default();
|
||||||
let concurrency = Concurrency::default();
|
let concurrency = Concurrency::default();
|
||||||
let config_settings = ConfigSettings::default();
|
let config_settings = ConfigSettings::default();
|
||||||
|
|
@ -187,6 +190,7 @@ mod resolver {
|
||||||
&config_settings,
|
&config_settings,
|
||||||
&config_settings_package,
|
&config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
LinkMode::default(),
|
LinkMode::default(),
|
||||||
&build_options,
|
&build_options,
|
||||||
&hashes,
|
&hashes,
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::fmt::Formatter;
|
use std::fmt::Formatter;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
@ -42,6 +43,7 @@ use uv_static::EnvVars;
|
||||||
use uv_types::{AnyErrorBuild, BuildContext, BuildIsolation, BuildStack, SourceBuildTrait};
|
use uv_types::{AnyErrorBuild, BuildContext, BuildIsolation, BuildStack, SourceBuildTrait};
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
use uv_workspace::WorkspaceCache;
|
use uv_workspace::WorkspaceCache;
|
||||||
|
use uv_workspace::pyproject::ExtraBuildDependencies;
|
||||||
|
|
||||||
pub use crate::error::{Error, MissingHeaderCause};
|
pub use crate::error::{Error, MissingHeaderCause};
|
||||||
|
|
||||||
|
|
@ -281,6 +283,7 @@ impl SourceBuild {
|
||||||
workspace_cache: &WorkspaceCache,
|
workspace_cache: &WorkspaceCache,
|
||||||
config_settings: ConfigSettings,
|
config_settings: ConfigSettings,
|
||||||
build_isolation: BuildIsolation<'_>,
|
build_isolation: BuildIsolation<'_>,
|
||||||
|
extra_build_dependencies: &ExtraBuildDependencies,
|
||||||
build_stack: &BuildStack,
|
build_stack: &BuildStack,
|
||||||
build_kind: BuildKind,
|
build_kind: BuildKind,
|
||||||
mut environment_variables: FxHashMap<OsString, OsString>,
|
mut environment_variables: FxHashMap<OsString, OsString>,
|
||||||
|
|
@ -297,7 +300,6 @@ impl SourceBuild {
|
||||||
};
|
};
|
||||||
|
|
||||||
let default_backend: Pep517Backend = DEFAULT_BACKEND.clone();
|
let default_backend: Pep517Backend = DEFAULT_BACKEND.clone();
|
||||||
|
|
||||||
// Check if we have a PEP 517 build backend.
|
// Check if we have a PEP 517 build backend.
|
||||||
let (pep517_backend, project) = Self::extract_pep517_backend(
|
let (pep517_backend, project) = Self::extract_pep517_backend(
|
||||||
&source_tree,
|
&source_tree,
|
||||||
|
|
@ -322,6 +324,14 @@ impl SourceBuild {
|
||||||
.or(fallback_package_version)
|
.or(fallback_package_version)
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
||||||
|
let extra_build_dependencies = package_name
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|name| extra_build_dependencies.get(name).cloned())
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.map(Requirement::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Create a virtual environment, or install into the shared environment if requested.
|
// Create a virtual environment, or install into the shared environment if requested.
|
||||||
let venv = if let Some(venv) = build_isolation.shared_environment(package_name.as_ref()) {
|
let venv = if let Some(venv) = build_isolation.shared_environment(package_name.as_ref()) {
|
||||||
venv.clone()
|
venv.clone()
|
||||||
|
|
@ -349,10 +359,13 @@ impl SourceBuild {
|
||||||
source_build_context,
|
source_build_context,
|
||||||
&default_backend,
|
&default_backend,
|
||||||
&pep517_backend,
|
&pep517_backend,
|
||||||
|
extra_build_dependencies,
|
||||||
build_stack,
|
build_stack,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
// TODO(zanieb): We'll report `build-system.requires` here but it may include
|
||||||
|
// `extra-build-dependencies`
|
||||||
build_context
|
build_context
|
||||||
.install(&resolved_requirements, &venv, build_stack)
|
.install(&resolved_requirements, &venv, build_stack)
|
||||||
.await
|
.await
|
||||||
|
|
@ -471,10 +484,13 @@ impl SourceBuild {
|
||||||
source_build_context: SourceBuildContext,
|
source_build_context: SourceBuildContext,
|
||||||
default_backend: &Pep517Backend,
|
default_backend: &Pep517Backend,
|
||||||
pep517_backend: &Pep517Backend,
|
pep517_backend: &Pep517Backend,
|
||||||
|
extra_build_dependencies: Vec<Requirement>,
|
||||||
build_stack: &BuildStack,
|
build_stack: &BuildStack,
|
||||||
) -> Result<Resolution, Error> {
|
) -> Result<Resolution, Error> {
|
||||||
Ok(
|
Ok(
|
||||||
if pep517_backend.requirements == default_backend.requirements {
|
if pep517_backend.requirements == default_backend.requirements
|
||||||
|
&& extra_build_dependencies.is_empty()
|
||||||
|
{
|
||||||
let mut resolution = source_build_context.default_resolution.lock().await;
|
let mut resolution = source_build_context.default_resolution.lock().await;
|
||||||
if let Some(resolved_requirements) = &*resolution {
|
if let Some(resolved_requirements) = &*resolution {
|
||||||
resolved_requirements.clone()
|
resolved_requirements.clone()
|
||||||
|
|
@ -489,8 +505,21 @@ impl SourceBuild {
|
||||||
resolved_requirements
|
resolved_requirements
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO(zanieb): It's unclear if we actually want to solve these together. We might
|
||||||
|
// want to perform a separate solve to allow conflicts?
|
||||||
|
let requirements = if extra_build_dependencies.is_empty() {
|
||||||
|
Cow::Borrowed(&pep517_backend.requirements)
|
||||||
|
} else {
|
||||||
|
// If there are extra build dependencies, we need to resolve them together with
|
||||||
|
// the backend requirements.
|
||||||
|
let mut requirements = pep517_backend.requirements.clone();
|
||||||
|
requirements.extend(extra_build_dependencies);
|
||||||
|
Cow::Owned(requirements)
|
||||||
|
};
|
||||||
|
// TODO(zanieb): We'll report `build-system.requires` here but it may include
|
||||||
|
// `extra-build-dependencies`
|
||||||
build_context
|
build_context
|
||||||
.resolve(&pep517_backend.requirements, build_stack)
|
.resolve(&requirements, build_stack)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
Error::RequirementsResolve("`build-system.requires`", err.into())
|
Error::RequirementsResolve("`build-system.requires`", err.into())
|
||||||
|
|
@ -604,6 +633,7 @@ impl SourceBuild {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
default_backend.clone()
|
default_backend.clone()
|
||||||
};
|
};
|
||||||
Ok((backend, pyproject_toml.project))
|
Ok((backend, pyproject_toml.project))
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,7 @@ pub fn resolver_options(
|
||||||
}),
|
}),
|
||||||
no_build_isolation: flag(no_build_isolation, build_isolation, "build-isolation"),
|
no_build_isolation: flag(no_build_isolation, build_isolation, "build-isolation"),
|
||||||
no_build_isolation_package: Some(no_build_isolation_package),
|
no_build_isolation_package: Some(no_build_isolation_package),
|
||||||
|
extra_build_dependencies: None,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
link_mode,
|
link_mode,
|
||||||
no_build: flag(no_build, build, "build"),
|
no_build: flag(no_build, build, "build"),
|
||||||
|
|
@ -465,6 +466,7 @@ pub fn resolver_installer_options(
|
||||||
} else {
|
} else {
|
||||||
Some(no_build_isolation_package)
|
Some(no_build_isolation_package)
|
||||||
},
|
},
|
||||||
|
extra_build_dependencies: None,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
link_mode,
|
link_mode,
|
||||||
compile_bytecode: flag(compile_bytecode, no_compile_bytecode, "compile-bytecode"),
|
compile_bytecode: flag(compile_bytecode, no_compile_bytecode, "compile-bytecode"),
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ bitflags::bitflags! {
|
||||||
const PYLOCK = 1 << 3;
|
const PYLOCK = 1 << 3;
|
||||||
const ADD_BOUNDS = 1 << 4;
|
const ADD_BOUNDS = 1 << 4;
|
||||||
const PREFER_LOCKED_BUILDS = 1 << 5;
|
const PREFER_LOCKED_BUILDS = 1 << 5;
|
||||||
|
const EXTRA_BUILD_DEPENDENCIES = 1 << 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -30,6 +31,7 @@ impl PreviewFeatures {
|
||||||
Self::PYLOCK => "pylock",
|
Self::PYLOCK => "pylock",
|
||||||
Self::ADD_BOUNDS => "add-bounds",
|
Self::ADD_BOUNDS => "add-bounds",
|
||||||
Self::PREFER_LOCKED_BUILDS => "prefer-locked-builds",
|
Self::PREFER_LOCKED_BUILDS => "prefer-locked-builds",
|
||||||
|
Self::EXTRA_BUILD_DEPENDENCIES => "extra-build-dependencies",
|
||||||
_ => panic!("`flag_as_str` can only be used for exactly one feature flag"),
|
_ => panic!("`flag_as_str` can only be used for exactly one feature flag"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -73,6 +75,7 @@ impl FromStr for PreviewFeatures {
|
||||||
"pylock" => Self::PYLOCK,
|
"pylock" => Self::PYLOCK,
|
||||||
"add-bounds" => Self::ADD_BOUNDS,
|
"add-bounds" => Self::ADD_BOUNDS,
|
||||||
"prefer-locked-builds" => Self::PREFER_LOCKED_BUILDS,
|
"prefer-locked-builds" => Self::PREFER_LOCKED_BUILDS,
|
||||||
|
"extra-build-dependencies" => Self::EXTRA_BUILD_DEPENDENCIES,
|
||||||
_ => {
|
_ => {
|
||||||
warn_user_once!("Unknown preview feature: `{part}`");
|
warn_user_once!("Unknown preview feature: `{part}`");
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -239,6 +242,10 @@ mod tests {
|
||||||
PreviewFeatures::PREFER_LOCKED_BUILDS.flag_as_str(),
|
PreviewFeatures::PREFER_LOCKED_BUILDS.flag_as_str(),
|
||||||
"prefer-locked-builds"
|
"prefer-locked-builds"
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES.flag_as_str(),
|
||||||
|
"extra-build-dependencies"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ use uv_configuration::{
|
||||||
};
|
};
|
||||||
use uv_configuration::{BuildOutput, Concurrency};
|
use uv_configuration::{BuildOutput, Concurrency};
|
||||||
use uv_distribution::DistributionDatabase;
|
use uv_distribution::DistributionDatabase;
|
||||||
|
use uv_distribution::ExtraBuildRequires;
|
||||||
use uv_distribution_filename::DistFilename;
|
use uv_distribution_filename::DistFilename;
|
||||||
use uv_distribution_types::{
|
use uv_distribution_types::{
|
||||||
CachedDist, DependencyMetadata, Identifier, IndexCapabilities, IndexLocations,
|
CachedDist, DependencyMetadata, Identifier, IndexCapabilities, IndexLocations,
|
||||||
|
|
@ -88,6 +89,7 @@ pub struct BuildDispatch<'a> {
|
||||||
shared_state: SharedState,
|
shared_state: SharedState,
|
||||||
dependency_metadata: &'a DependencyMetadata,
|
dependency_metadata: &'a DependencyMetadata,
|
||||||
build_isolation: BuildIsolation<'a>,
|
build_isolation: BuildIsolation<'a>,
|
||||||
|
extra_build_requires: &'a ExtraBuildRequires,
|
||||||
link_mode: uv_install_wheel::LinkMode,
|
link_mode: uv_install_wheel::LinkMode,
|
||||||
build_options: &'a BuildOptions,
|
build_options: &'a BuildOptions,
|
||||||
config_settings: &'a ConfigSettings,
|
config_settings: &'a ConfigSettings,
|
||||||
|
|
@ -117,6 +119,7 @@ impl<'a> BuildDispatch<'a> {
|
||||||
config_settings: &'a ConfigSettings,
|
config_settings: &'a ConfigSettings,
|
||||||
config_settings_package: &'a PackageConfigSettings,
|
config_settings_package: &'a PackageConfigSettings,
|
||||||
build_isolation: BuildIsolation<'a>,
|
build_isolation: BuildIsolation<'a>,
|
||||||
|
extra_build_requires: &'a ExtraBuildRequires,
|
||||||
link_mode: uv_install_wheel::LinkMode,
|
link_mode: uv_install_wheel::LinkMode,
|
||||||
build_options: &'a BuildOptions,
|
build_options: &'a BuildOptions,
|
||||||
hasher: &'a HashStrategy,
|
hasher: &'a HashStrategy,
|
||||||
|
|
@ -140,6 +143,7 @@ impl<'a> BuildDispatch<'a> {
|
||||||
config_settings,
|
config_settings,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
extra_build_requires,
|
||||||
link_mode,
|
link_mode,
|
||||||
build_options,
|
build_options,
|
||||||
hasher,
|
hasher,
|
||||||
|
|
@ -222,6 +226,10 @@ impl BuildContext for BuildDispatch<'_> {
|
||||||
&self.workspace_cache
|
&self.workspace_cache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extra_build_dependencies(&self) -> &uv_workspace::pyproject::ExtraBuildDependencies {
|
||||||
|
&self.extra_build_requires.extra_build_dependencies
|
||||||
|
}
|
||||||
|
|
||||||
async fn resolve<'data>(
|
async fn resolve<'data>(
|
||||||
&'data self,
|
&'data self,
|
||||||
requirements: &'data [Requirement],
|
requirements: &'data [Requirement],
|
||||||
|
|
@ -457,6 +465,7 @@ impl BuildContext for BuildDispatch<'_> {
|
||||||
self.workspace_cache(),
|
self.workspace_cache(),
|
||||||
config_settings,
|
config_settings,
|
||||||
self.build_isolation,
|
self.build_isolation,
|
||||||
|
&self.extra_build_requires.extra_build_dependencies,
|
||||||
&build_stack,
|
&build_stack,
|
||||||
build_kind,
|
build_kind,
|
||||||
self.build_extra_env_vars.clone(),
|
self.build_extra_env_vars.clone(),
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ pub use download::LocalWheel;
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use index::{BuiltWheelIndex, RegistryWheelIndex};
|
pub use index::{BuiltWheelIndex, RegistryWheelIndex};
|
||||||
pub use metadata::{
|
pub use metadata::{
|
||||||
ArchiveMetadata, BuildRequires, FlatRequiresDist, LoweredRequirement, LoweringError, Metadata,
|
ArchiveMetadata, BuildRequires, ExtraBuildRequires, FlatRequiresDist, LoweredRequirement,
|
||||||
MetadataError, RequiresDist, SourcedDependencyGroups,
|
LoweringError, Metadata, MetadataError, RequiresDist, SourcedDependencyGroups,
|
||||||
};
|
};
|
||||||
pub use reporter::Reporter;
|
pub use reporter::Reporter;
|
||||||
pub use source::prune;
|
pub use source::prune;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ use std::path::Path;
|
||||||
use uv_configuration::SourceStrategy;
|
use uv_configuration::SourceStrategy;
|
||||||
use uv_distribution_types::{IndexLocations, Requirement};
|
use uv_distribution_types::{IndexLocations, Requirement};
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_workspace::pyproject::ToolUvSources;
|
use uv_pypi_types::VerbatimParsedUrl;
|
||||||
|
use uv_workspace::pyproject::{ExtraBuildDependencies, ToolUvSources};
|
||||||
use uv_workspace::{
|
use uv_workspace::{
|
||||||
DiscoveryOptions, MemberDiscovery, ProjectWorkspace, Workspace, WorkspaceCache,
|
DiscoveryOptions, MemberDiscovery, ProjectWorkspace, Workspace, WorkspaceCache,
|
||||||
};
|
};
|
||||||
|
|
@ -203,3 +204,93 @@ impl BuildRequires {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lowered extra build dependencies with source resolution applied.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ExtraBuildRequires {
|
||||||
|
pub extra_build_dependencies: ExtraBuildDependencies,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtraBuildRequires {
|
||||||
|
/// Lower extra build dependencies from a workspace, applying source resolution.
|
||||||
|
pub fn from_workspace(
|
||||||
|
extra_build_dependencies: ExtraBuildDependencies,
|
||||||
|
workspace: &Workspace,
|
||||||
|
index_locations: &IndexLocations,
|
||||||
|
source_strategy: SourceStrategy,
|
||||||
|
) -> Result<Self, MetadataError> {
|
||||||
|
match source_strategy {
|
||||||
|
SourceStrategy::Enabled => {
|
||||||
|
// Collect project sources and indexes
|
||||||
|
let project_indexes = workspace
|
||||||
|
.pyproject_toml()
|
||||||
|
.tool
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|tool| tool.uv.as_ref())
|
||||||
|
.and_then(|uv| uv.index.as_deref())
|
||||||
|
.unwrap_or(&[]);
|
||||||
|
|
||||||
|
let empty_sources = BTreeMap::default();
|
||||||
|
let project_sources = workspace
|
||||||
|
.pyproject_toml()
|
||||||
|
.tool
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|tool| tool.uv.as_ref())
|
||||||
|
.and_then(|uv| uv.sources.as_ref())
|
||||||
|
.map(ToolUvSources::inner)
|
||||||
|
.unwrap_or(&empty_sources);
|
||||||
|
|
||||||
|
// Lower each package's extra build dependencies
|
||||||
|
let mut result = ExtraBuildDependencies::default();
|
||||||
|
for (package_name, requirements) in extra_build_dependencies {
|
||||||
|
let lowered: Vec<uv_pep508::Requirement<VerbatimParsedUrl>> = requirements
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|requirement| {
|
||||||
|
let requirement_name = requirement.name.clone();
|
||||||
|
let extra = requirement.marker.top_level_extra_name();
|
||||||
|
let group = None;
|
||||||
|
LoweredRequirement::from_requirement(
|
||||||
|
requirement,
|
||||||
|
None,
|
||||||
|
workspace.install_path(),
|
||||||
|
project_sources,
|
||||||
|
project_indexes,
|
||||||
|
extra.as_deref(),
|
||||||
|
group,
|
||||||
|
index_locations,
|
||||||
|
workspace,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.map(
|
||||||
|
move |requirement| match requirement {
|
||||||
|
Ok(requirement) => Ok(requirement.into_inner().into()),
|
||||||
|
Err(err) => Err(MetadataError::LoweringError(
|
||||||
|
requirement_name.clone(),
|
||||||
|
Box::new(err),
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
result.insert(package_name, lowered);
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
extra_build_dependencies: result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
SourceStrategy::Disabled => {
|
||||||
|
// Without source resolution, just return the dependencies as-is
|
||||||
|
Ok(Self {
|
||||||
|
extra_build_dependencies,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create from pre-lowered dependencies (for non-workspace contexts).
|
||||||
|
pub fn from_lowered(extra_build_dependencies: ExtraBuildDependencies) -> Self {
|
||||||
|
Self {
|
||||||
|
extra_build_dependencies,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use uv_pypi_types::{HashDigests, ResolutionMetadata};
|
||||||
use uv_workspace::dependency_groups::DependencyGroupError;
|
use uv_workspace::dependency_groups::DependencyGroupError;
|
||||||
use uv_workspace::{WorkspaceCache, WorkspaceError};
|
use uv_workspace::{WorkspaceCache, WorkspaceError};
|
||||||
|
|
||||||
pub use crate::metadata::build_requires::BuildRequires;
|
pub use crate::metadata::build_requires::{BuildRequires, ExtraBuildRequires};
|
||||||
pub use crate::metadata::dependency_groups::SourcedDependencyGroups;
|
pub use crate::metadata::dependency_groups::SourcedDependencyGroups;
|
||||||
pub use crate::metadata::lowering::LoweredRequirement;
|
pub use crate::metadata::lowering::LoweredRequirement;
|
||||||
pub use crate::metadata::lowering::LoweringError;
|
pub use crate::metadata::lowering::LoweringError;
|
||||||
|
|
|
||||||
|
|
@ -404,6 +404,20 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determine the extra build dependencies for the given package name.
|
||||||
|
fn extra_build_dependencies_for(
|
||||||
|
&self,
|
||||||
|
name: Option<&PackageName>,
|
||||||
|
) -> &[uv_pep508::Requirement<uv_pypi_types::VerbatimParsedUrl>] {
|
||||||
|
name.and_then(|name| {
|
||||||
|
self.build_context
|
||||||
|
.extra_build_dependencies()
|
||||||
|
.get(name)
|
||||||
|
.map(|v| v.as_slice())
|
||||||
|
})
|
||||||
|
.unwrap_or(&[])
|
||||||
|
}
|
||||||
|
|
||||||
/// Build a source distribution from a remote URL.
|
/// Build a source distribution from a remote URL.
|
||||||
async fn url<'data>(
|
async fn url<'data>(
|
||||||
&self,
|
&self,
|
||||||
|
|
@ -438,12 +452,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
let cache_shard = cache_shard.shard(revision.id());
|
let cache_shard = cache_shard.shard(revision.id());
|
||||||
let source_dist_entry = cache_shard.entry(SOURCE);
|
let source_dist_entry = cache_shard.entry(SOURCE);
|
||||||
|
|
||||||
// If there are build settings, we need to scope to a cache shard.
|
// If there are build settings or extra build dependencies, we need to scope to a cache shard.
|
||||||
let config_settings = self.config_settings_for(source.name());
|
let config_settings = self.config_settings_for(source.name());
|
||||||
let cache_shard = if config_settings.is_empty() {
|
let extra_build_deps = self.extra_build_dependencies_for(source.name());
|
||||||
|
let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() {
|
||||||
cache_shard
|
cache_shard
|
||||||
} else {
|
} else {
|
||||||
cache_shard.shard(cache_digest(&&config_settings))
|
cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps)))
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the cache contains a compatible wheel, return it.
|
// If the cache contains a compatible wheel, return it.
|
||||||
|
|
@ -614,12 +629,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are build settings, we need to scope to a cache shard.
|
// If there are build settings or extra build dependencies, we need to scope to a cache shard.
|
||||||
let config_settings = self.config_settings_for(source.name());
|
let config_settings = self.config_settings_for(source.name());
|
||||||
let cache_shard = if config_settings.is_empty() {
|
let extra_build_deps = self.extra_build_dependencies_for(source.name());
|
||||||
|
let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() {
|
||||||
cache_shard
|
cache_shard
|
||||||
} else {
|
} else {
|
||||||
cache_shard.shard(cache_digest(&config_settings))
|
cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps)))
|
||||||
};
|
};
|
||||||
|
|
||||||
// Otherwise, we either need to build the metadata.
|
// Otherwise, we either need to build the metadata.
|
||||||
|
|
@ -827,12 +843,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
let cache_shard = cache_shard.shard(revision.id());
|
let cache_shard = cache_shard.shard(revision.id());
|
||||||
let source_entry = cache_shard.entry(SOURCE);
|
let source_entry = cache_shard.entry(SOURCE);
|
||||||
|
|
||||||
// If there are build settings, we need to scope to a cache shard.
|
// If there are build settings or extra build dependencies, we need to scope to a cache shard.
|
||||||
let config_settings = self.config_settings_for(source.name());
|
let config_settings = self.config_settings_for(source.name());
|
||||||
let cache_shard = if config_settings.is_empty() {
|
let extra_build_deps = self.extra_build_dependencies_for(source.name());
|
||||||
|
let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() {
|
||||||
cache_shard
|
cache_shard
|
||||||
} else {
|
} else {
|
||||||
cache_shard.shard(cache_digest(&config_settings))
|
cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps)))
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the cache contains a compatible wheel, return it.
|
// If the cache contains a compatible wheel, return it.
|
||||||
|
|
@ -989,12 +1006,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are build settings, we need to scope to a cache shard.
|
// If there are build settings or extra build dependencies, we need to scope to a cache shard.
|
||||||
let config_settings = self.config_settings_for(source.name());
|
let config_settings = self.config_settings_for(source.name());
|
||||||
let cache_shard = if config_settings.is_empty() {
|
let extra_build_deps = self.extra_build_dependencies_for(source.name());
|
||||||
|
let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() {
|
||||||
cache_shard
|
cache_shard
|
||||||
} else {
|
} else {
|
||||||
cache_shard.shard(cache_digest(&config_settings))
|
cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps)))
|
||||||
};
|
};
|
||||||
|
|
||||||
// Otherwise, we need to build a wheel.
|
// Otherwise, we need to build a wheel.
|
||||||
|
|
@ -1131,12 +1149,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
// freshness, since entries have to be fresher than the revision itself.
|
// freshness, since entries have to be fresher than the revision itself.
|
||||||
let cache_shard = cache_shard.shard(revision.id());
|
let cache_shard = cache_shard.shard(revision.id());
|
||||||
|
|
||||||
// If there are build settings, we need to scope to a cache shard.
|
// If there are build settings or extra build dependencies, we need to scope to a cache shard.
|
||||||
let config_settings = self.config_settings_for(source.name());
|
let config_settings = self.config_settings_for(source.name());
|
||||||
let cache_shard = if config_settings.is_empty() {
|
let extra_build_deps = self.extra_build_dependencies_for(source.name());
|
||||||
|
let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() {
|
||||||
cache_shard
|
cache_shard
|
||||||
} else {
|
} else {
|
||||||
cache_shard.shard(cache_digest(&config_settings))
|
cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps)))
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the cache contains a compatible wheel, return it.
|
// If the cache contains a compatible wheel, return it.
|
||||||
|
|
@ -1319,12 +1338,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are build settings, we need to scope to a cache shard.
|
// If there are build settings or extra build dependencies, we need to scope to a cache shard.
|
||||||
let config_settings = self.config_settings_for(source.name());
|
let config_settings = self.config_settings_for(source.name());
|
||||||
let cache_shard = if config_settings.is_empty() {
|
let extra_build_deps = self.extra_build_dependencies_for(source.name());
|
||||||
|
let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() {
|
||||||
cache_shard
|
cache_shard
|
||||||
} else {
|
} else {
|
||||||
cache_shard.shard(cache_digest(&config_settings))
|
cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps)))
|
||||||
};
|
};
|
||||||
|
|
||||||
// Otherwise, we need to build a wheel.
|
// Otherwise, we need to build a wheel.
|
||||||
|
|
@ -1524,12 +1544,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
// Acquire the advisory lock.
|
// Acquire the advisory lock.
|
||||||
let _lock = cache_shard.lock().await.map_err(Error::CacheWrite)?;
|
let _lock = cache_shard.lock().await.map_err(Error::CacheWrite)?;
|
||||||
|
|
||||||
// If there are build settings, we need to scope to a cache shard.
|
// If there are build settings or extra build dependencies, we need to scope to a cache shard.
|
||||||
let config_settings = self.config_settings_for(source.name());
|
let config_settings = self.config_settings_for(source.name());
|
||||||
let cache_shard = if config_settings.is_empty() {
|
let extra_build_deps = self.extra_build_dependencies_for(source.name());
|
||||||
|
let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() {
|
||||||
cache_shard
|
cache_shard
|
||||||
} else {
|
} else {
|
||||||
cache_shard.shard(cache_digest(&config_settings))
|
cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps)))
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the cache contains a compatible wheel, return it.
|
// If the cache contains a compatible wheel, return it.
|
||||||
|
|
@ -1827,12 +1848,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are build settings, we need to scope to a cache shard.
|
// If there are build settings or extra build dependencies, we need to scope to a cache shard.
|
||||||
let config_settings = self.config_settings_for(source.name());
|
let config_settings = self.config_settings_for(source.name());
|
||||||
let cache_shard = if config_settings.is_empty() {
|
let extra_build_deps = self.extra_build_dependencies_for(source.name());
|
||||||
|
let cache_shard = if config_settings.is_empty() && extra_build_deps.is_empty() {
|
||||||
cache_shard
|
cache_shard
|
||||||
} else {
|
} else {
|
||||||
cache_shard.shard(cache_digest(&config_settings))
|
cache_shard.shard(cache_digest(&(&config_settings, extra_build_deps)))
|
||||||
};
|
};
|
||||||
|
|
||||||
// Otherwise, we need to build a wheel.
|
// Otherwise, we need to build a wheel.
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,24 @@ impl Operator {
|
||||||
pub fn is_star(self) -> bool {
|
pub fn is_star(self) -> bool {
|
||||||
matches!(self, Self::EqualStar | Self::NotEqualStar)
|
matches!(self, Self::EqualStar | Self::NotEqualStar)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the string representation of this operator.
|
||||||
|
pub fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Equal => "==",
|
||||||
|
// Beware, this doesn't print the star
|
||||||
|
Self::EqualStar => "==",
|
||||||
|
#[allow(deprecated)]
|
||||||
|
Self::ExactEqual => "===",
|
||||||
|
Self::NotEqual => "!=",
|
||||||
|
Self::NotEqualStar => "!=",
|
||||||
|
Self::TildeEqual => "~=",
|
||||||
|
Self::LessThan => "<",
|
||||||
|
Self::LessThanEqual => "<=",
|
||||||
|
Self::GreaterThan => ">",
|
||||||
|
Self::GreaterThanEqual => ">=",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Operator {
|
impl FromStr for Operator {
|
||||||
|
|
@ -150,21 +168,7 @@ impl FromStr for Operator {
|
||||||
impl std::fmt::Display for Operator {
|
impl std::fmt::Display for Operator {
|
||||||
/// Note the `EqualStar` is also `==`.
|
/// Note the `EqualStar` is also `==`.
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let operator = match self {
|
let operator = self.as_str();
|
||||||
Self::Equal => "==",
|
|
||||||
// Beware, this doesn't print the star
|
|
||||||
Self::EqualStar => "==",
|
|
||||||
#[allow(deprecated)]
|
|
||||||
Self::ExactEqual => "===",
|
|
||||||
Self::NotEqual => "!=",
|
|
||||||
Self::NotEqualStar => "!=",
|
|
||||||
Self::TildeEqual => "~=",
|
|
||||||
Self::LessThan => "<",
|
|
||||||
Self::LessThanEqual => "<=",
|
|
||||||
Self::GreaterThan => ">",
|
|
||||||
Self::GreaterThanEqual => ">=",
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(f, "{operator}")
|
write!(f, "{operator}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,11 @@ impl VersionSpecifiers {
|
||||||
Self(Box::new([]))
|
Self(Box::new([]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The number of specifiers.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.0.len()
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether all specifiers match the given version.
|
/// Whether all specifiers match the given version.
|
||||||
pub fn contains(&self, version: &Version) -> bool {
|
pub fn contains(&self, version: &Version) -> bool {
|
||||||
self.iter().all(|specifier| specifier.contains(version))
|
self.iter().all(|specifier| specifier.contains(version))
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ doctest = false
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
uv-cache-key = { workspace = true }
|
||||||
uv-fs = { workspace = true }
|
uv-fs = { workspace = true }
|
||||||
uv-normalize = { workspace = true }
|
uv-normalize = { workspace = true }
|
||||||
uv-pep440 = { workspace = true }
|
uv-pep440 = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ use std::str::FromStr;
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
use uv_cache_key::{CacheKey, CacheKeyHasher};
|
||||||
|
|
||||||
use cursor::Cursor;
|
use cursor::Cursor;
|
||||||
pub use marker::{
|
pub use marker::{
|
||||||
|
|
@ -251,6 +252,52 @@ impl<T: Pep508Url> Serialize for Requirement<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Pep508Url> CacheKey for Requirement<T>
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
{
|
||||||
|
fn cache_key(&self, state: &mut CacheKeyHasher) {
|
||||||
|
self.name.as_str().cache_key(state);
|
||||||
|
|
||||||
|
self.extras.len().cache_key(state);
|
||||||
|
for extra in &self.extras {
|
||||||
|
extra.as_str().cache_key(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(zanieb): We inline cache key handling for the child types here, but we could
|
||||||
|
// move the implementations to the children. The intent here was to limit the scope of
|
||||||
|
// types exposing the `CacheKey` trait for now.
|
||||||
|
if let Some(version_or_url) = &self.version_or_url {
|
||||||
|
1u8.cache_key(state);
|
||||||
|
match version_or_url {
|
||||||
|
VersionOrUrl::VersionSpecifier(spec) => {
|
||||||
|
0u8.cache_key(state);
|
||||||
|
spec.len().cache_key(state);
|
||||||
|
for specifier in spec.iter() {
|
||||||
|
specifier.operator().as_str().cache_key(state);
|
||||||
|
specifier.version().to_string().cache_key(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VersionOrUrl::Url(url) => {
|
||||||
|
1u8.cache_key(state);
|
||||||
|
url.to_string().cache_key(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
0u8.cache_key(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(marker) = self.marker.contents() {
|
||||||
|
1u8.cache_key(state);
|
||||||
|
marker.to_string().cache_key(state);
|
||||||
|
} else {
|
||||||
|
0u8.cache_key(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// `origin` is intentionally omitted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Pep508Url> Requirement<T> {
|
impl<T: Pep508Url> Requirement<T> {
|
||||||
/// Returns whether the markers apply for the given environment
|
/// Returns whether the markers apply for the given environment
|
||||||
pub fn evaluate_markers(&self, env: &MarkerEnvironment, extras: &[ExtraName]) -> bool {
|
pub fn evaluate_markers(&self, env: &MarkerEnvironment, extras: &[ExtraName]) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -381,6 +381,8 @@ pub struct ToolUv {
|
||||||
pub override_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
pub override_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
||||||
pub constraint_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
pub constraint_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
||||||
pub build_constraint_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
pub build_constraint_dependencies: Option<Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>,
|
||||||
|
pub extra_build_dependencies:
|
||||||
|
Option<BTreeMap<PackageName, Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>>,
|
||||||
pub sources: Option<BTreeMap<PackageName, Sources>>,
|
pub sources: Option<BTreeMap<PackageName, Sources>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use std::num::NonZeroUsize;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::{collections::BTreeMap, num::NonZeroUsize};
|
||||||
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
|
@ -121,6 +121,21 @@ impl<T> Combine for Option<Vec<T>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<K: Ord, T> Combine for Option<BTreeMap<K, Vec<T>>> {
|
||||||
|
/// Combine two maps of vecs by combining their vecs
|
||||||
|
fn combine(self, other: Option<BTreeMap<K, Vec<T>>>) -> Option<BTreeMap<K, Vec<T>>> {
|
||||||
|
match (self, other) {
|
||||||
|
(Some(mut a), Some(b)) => {
|
||||||
|
for (key, value) in b {
|
||||||
|
a.entry(key).or_default().extend(value);
|
||||||
|
}
|
||||||
|
Some(a)
|
||||||
|
}
|
||||||
|
(a, b) => a.or(b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Combine for Option<ConfigSettings> {
|
impl Combine for Option<ConfigSettings> {
|
||||||
/// Combine two maps by merging the map in `self` with the map in `other`, if they're both
|
/// Combine two maps by merging the map in `self` with the map in `other`, if they're both
|
||||||
/// `Some`.
|
/// `Some`.
|
||||||
|
|
|
||||||
|
|
@ -317,6 +317,7 @@ fn warn_uv_toml_masked_fields(options: &Options) {
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
link_mode,
|
link_mode,
|
||||||
compile_bytecode,
|
compile_bytecode,
|
||||||
|
|
@ -445,6 +446,9 @@ fn warn_uv_toml_masked_fields(options: &Options) {
|
||||||
if no_build_isolation_package.is_some() {
|
if no_build_isolation_package.is_some() {
|
||||||
masked_fields.push("no-build-isolation-package");
|
masked_fields.push("no-build-isolation-package");
|
||||||
}
|
}
|
||||||
|
if extra_build_dependencies.is_some() {
|
||||||
|
masked_fields.push("extra-build-dependencies");
|
||||||
|
}
|
||||||
if exclude_newer.is_some() {
|
if exclude_newer.is_some() {
|
||||||
masked_fields.push("exclude-newer");
|
masked_fields.push("exclude-newer");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ use uv_redacted::DisplaySafeUrl;
|
||||||
use uv_resolver::{AnnotationStyle, ExcludeNewer, ForkStrategy, PrereleaseMode, ResolutionMode};
|
use uv_resolver::{AnnotationStyle, ExcludeNewer, ForkStrategy, PrereleaseMode, ResolutionMode};
|
||||||
use uv_static::EnvVars;
|
use uv_static::EnvVars;
|
||||||
use uv_torch::TorchMode;
|
use uv_torch::TorchMode;
|
||||||
use uv_workspace::pyproject_mut::AddBoundsKind;
|
use uv_workspace::{pyproject::ExtraBuildDependencies, pyproject_mut::AddBoundsKind};
|
||||||
|
|
||||||
/// A `pyproject.toml` with an (optional) `[tool.uv]` section.
|
/// A `pyproject.toml` with an (optional) `[tool.uv]` section.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
@ -373,6 +373,7 @@ pub struct ResolverOptions {
|
||||||
pub no_binary_package: Option<Vec<PackageName>>,
|
pub no_binary_package: Option<Vec<PackageName>>,
|
||||||
pub no_build_isolation: Option<bool>,
|
pub no_build_isolation: Option<bool>,
|
||||||
pub no_build_isolation_package: Option<Vec<PackageName>>,
|
pub no_build_isolation_package: Option<Vec<PackageName>>,
|
||||||
|
pub extra_build_dependencies: Option<ExtraBuildDependencies>,
|
||||||
pub no_sources: Option<bool>,
|
pub no_sources: Option<bool>,
|
||||||
pub build_dependency_strategy: Option<BuildDependencyStrategy>,
|
pub build_dependency_strategy: Option<BuildDependencyStrategy>,
|
||||||
}
|
}
|
||||||
|
|
@ -643,6 +644,20 @@ pub struct ResolverInstallerOptions {
|
||||||
"#
|
"#
|
||||||
)]
|
)]
|
||||||
pub no_build_isolation_package: Option<Vec<PackageName>>,
|
pub no_build_isolation_package: Option<Vec<PackageName>>,
|
||||||
|
/// Additional build dependencies for packages.
|
||||||
|
///
|
||||||
|
/// This allows extending the PEP 517 build environment for the project's dependencies with
|
||||||
|
/// additional packages. This is useful for packages that assume the presence of packages, like,
|
||||||
|
/// `pip`, and do not declare them as build dependencies.
|
||||||
|
#[option(
|
||||||
|
default = "[]",
|
||||||
|
value_type = "dict",
|
||||||
|
example = r#"
|
||||||
|
[extra-build-dependencies]
|
||||||
|
pytest = ["setuptools"]
|
||||||
|
"#
|
||||||
|
)]
|
||||||
|
pub extra_build_dependencies: Option<ExtraBuildDependencies>,
|
||||||
/// Limit candidate packages to those that were uploaded prior to a given point in time.
|
/// Limit candidate packages to those that were uploaded prior to a given point in time.
|
||||||
///
|
///
|
||||||
/// Accepts a superset of [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) (e.g.,
|
/// Accepts a superset of [RFC 3339](https://www.rfc-editor.org/rfc/rfc3339.html) (e.g.,
|
||||||
|
|
@ -1139,6 +1154,20 @@ pub struct PipOptions {
|
||||||
"#
|
"#
|
||||||
)]
|
)]
|
||||||
pub no_build_isolation_package: Option<Vec<PackageName>>,
|
pub no_build_isolation_package: Option<Vec<PackageName>>,
|
||||||
|
/// Additional build dependencies for packages.
|
||||||
|
///
|
||||||
|
/// This allows extending the PEP 517 build environment for the project's dependencies with
|
||||||
|
/// additional packages. This is useful for packages that assume the presence of packages, like,
|
||||||
|
/// `pip`, and do not declare them as build dependencies.
|
||||||
|
#[option(
|
||||||
|
default = "[]",
|
||||||
|
value_type = "dict",
|
||||||
|
example = r#"
|
||||||
|
[extra-build-dependencies]
|
||||||
|
pytest = ["setuptools"]
|
||||||
|
"#
|
||||||
|
)]
|
||||||
|
pub extra_build_dependencies: Option<ExtraBuildDependencies>,
|
||||||
/// Validate the Python environment, to detect packages with missing dependencies and other
|
/// Validate the Python environment, to detect packages with missing dependencies and other
|
||||||
/// issues.
|
/// issues.
|
||||||
#[option(
|
#[option(
|
||||||
|
|
@ -1704,6 +1733,7 @@ impl From<ResolverInstallerOptions> for ResolverOptions {
|
||||||
no_binary_package: value.no_binary_package,
|
no_binary_package: value.no_binary_package,
|
||||||
no_build_isolation: value.no_build_isolation,
|
no_build_isolation: value.no_build_isolation,
|
||||||
no_build_isolation_package: value.no_build_isolation_package,
|
no_build_isolation_package: value.no_build_isolation_package,
|
||||||
|
extra_build_dependencies: value.extra_build_dependencies,
|
||||||
no_sources: value.no_sources,
|
no_sources: value.no_sources,
|
||||||
build_dependency_strategy: value.build_dependency_strategy,
|
build_dependency_strategy: value.build_dependency_strategy,
|
||||||
}
|
}
|
||||||
|
|
@ -1761,6 +1791,7 @@ pub struct ToolOptions {
|
||||||
pub config_settings_package: Option<PackageConfigSettings>,
|
pub config_settings_package: Option<PackageConfigSettings>,
|
||||||
pub no_build_isolation: Option<bool>,
|
pub no_build_isolation: Option<bool>,
|
||||||
pub no_build_isolation_package: Option<Vec<PackageName>>,
|
pub no_build_isolation_package: Option<Vec<PackageName>>,
|
||||||
|
pub extra_build_dependencies: Option<ExtraBuildDependencies>,
|
||||||
pub exclude_newer: Option<ExcludeNewer>,
|
pub exclude_newer: Option<ExcludeNewer>,
|
||||||
pub link_mode: Option<LinkMode>,
|
pub link_mode: Option<LinkMode>,
|
||||||
pub compile_bytecode: Option<bool>,
|
pub compile_bytecode: Option<bool>,
|
||||||
|
|
@ -1789,6 +1820,7 @@ impl From<ResolverInstallerOptions> for ToolOptions {
|
||||||
config_settings_package: value.config_settings_package,
|
config_settings_package: value.config_settings_package,
|
||||||
no_build_isolation: value.no_build_isolation,
|
no_build_isolation: value.no_build_isolation,
|
||||||
no_build_isolation_package: value.no_build_isolation_package,
|
no_build_isolation_package: value.no_build_isolation_package,
|
||||||
|
extra_build_dependencies: value.extra_build_dependencies,
|
||||||
exclude_newer: value.exclude_newer,
|
exclude_newer: value.exclude_newer,
|
||||||
link_mode: value.link_mode,
|
link_mode: value.link_mode,
|
||||||
compile_bytecode: value.compile_bytecode,
|
compile_bytecode: value.compile_bytecode,
|
||||||
|
|
@ -1819,6 +1851,7 @@ impl From<ToolOptions> for ResolverInstallerOptions {
|
||||||
config_settings_package: value.config_settings_package,
|
config_settings_package: value.config_settings_package,
|
||||||
no_build_isolation: value.no_build_isolation,
|
no_build_isolation: value.no_build_isolation,
|
||||||
no_build_isolation_package: value.no_build_isolation_package,
|
no_build_isolation_package: value.no_build_isolation_package,
|
||||||
|
extra_build_dependencies: value.extra_build_dependencies,
|
||||||
exclude_newer: value.exclude_newer,
|
exclude_newer: value.exclude_newer,
|
||||||
link_mode: value.link_mode,
|
link_mode: value.link_mode,
|
||||||
compile_bytecode: value.compile_bytecode,
|
compile_bytecode: value.compile_bytecode,
|
||||||
|
|
@ -1873,6 +1906,7 @@ pub struct OptionsWire {
|
||||||
config_settings_package: Option<PackageConfigSettings>,
|
config_settings_package: Option<PackageConfigSettings>,
|
||||||
no_build_isolation: Option<bool>,
|
no_build_isolation: Option<bool>,
|
||||||
no_build_isolation_package: Option<Vec<PackageName>>,
|
no_build_isolation_package: Option<Vec<PackageName>>,
|
||||||
|
extra_build_dependencies: Option<ExtraBuildDependencies>,
|
||||||
exclude_newer: Option<ExcludeNewer>,
|
exclude_newer: Option<ExcludeNewer>,
|
||||||
link_mode: Option<LinkMode>,
|
link_mode: Option<LinkMode>,
|
||||||
compile_bytecode: Option<bool>,
|
compile_bytecode: Option<bool>,
|
||||||
|
|
@ -1992,6 +2026,7 @@ impl From<OptionsWire> for Options {
|
||||||
sources,
|
sources,
|
||||||
default_groups,
|
default_groups,
|
||||||
dependency_groups,
|
dependency_groups,
|
||||||
|
extra_build_dependencies,
|
||||||
dev_dependencies,
|
dev_dependencies,
|
||||||
managed,
|
managed,
|
||||||
package,
|
package,
|
||||||
|
|
@ -2033,6 +2068,7 @@ impl From<OptionsWire> for Options {
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
link_mode,
|
link_mode,
|
||||||
compile_bytecode,
|
compile_bytecode,
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,9 @@ pub trait BuildContext {
|
||||||
/// Workspace discovery caching.
|
/// Workspace discovery caching.
|
||||||
fn workspace_cache(&self) -> &WorkspaceCache;
|
fn workspace_cache(&self) -> &WorkspaceCache;
|
||||||
|
|
||||||
|
/// Get the extra build dependencies.
|
||||||
|
fn extra_build_dependencies(&self) -> &uv_workspace::pyproject::ExtraBuildDependencies;
|
||||||
|
|
||||||
/// Resolve the given requirements into a ready-to-install set of package versions.
|
/// Resolve the given requirements into a ready-to-install set of package versions.
|
||||||
fn resolve<'a>(
|
fn resolve<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
|
|
|
||||||
|
|
@ -378,6 +378,21 @@ pub struct ToolUv {
|
||||||
)]
|
)]
|
||||||
pub dependency_groups: Option<ToolUvDependencyGroups>,
|
pub dependency_groups: Option<ToolUvDependencyGroups>,
|
||||||
|
|
||||||
|
/// Additional build dependencies for packages.
|
||||||
|
///
|
||||||
|
/// This allows extending the PEP 517 build environment for the project's dependencies with
|
||||||
|
/// additional packages. This is useful for packages that assume the presence of packages, like,
|
||||||
|
/// `pip`, and do not declare them as build dependencies.
|
||||||
|
#[option(
|
||||||
|
default = "[]",
|
||||||
|
value_type = "dict",
|
||||||
|
example = r#"
|
||||||
|
[tool.uv.extra-build-dependencies]
|
||||||
|
pytest = ["pip"]
|
||||||
|
"#
|
||||||
|
)]
|
||||||
|
pub extra_build_dependencies: Option<ToolUvExtraBuildDependencies>,
|
||||||
|
|
||||||
/// The project's development dependencies.
|
/// The project's development dependencies.
|
||||||
///
|
///
|
||||||
/// Development dependencies will be installed by default in `uv run` and `uv sync`, but will
|
/// Development dependencies will be installed by default in `uv run` and `uv sync`, but will
|
||||||
|
|
@ -749,6 +764,70 @@ pub struct DependencyGroupSettings {
|
||||||
pub requires_python: Option<VersionSpecifiers>,
|
pub requires_python: Option<VersionSpecifiers>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type ExtraBuildDependencies =
|
||||||
|
BTreeMap<PackageName, Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>;
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(test, derive(Serialize))]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
|
pub struct ToolUvExtraBuildDependencies(ExtraBuildDependencies);
|
||||||
|
|
||||||
|
impl ToolUvExtraBuildDependencies {
|
||||||
|
/// Returns the underlying `BTreeMap` of group names to settings.
|
||||||
|
pub fn inner(&self) -> &ExtraBuildDependencies {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert the [`ToolUvExtraBuildDependencies`] into its inner `BTreeMap`.
|
||||||
|
#[must_use]
|
||||||
|
pub fn into_inner(self) -> ExtraBuildDependencies {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ensure that all keys in the TOML table are unique.
|
||||||
|
impl<'de> serde::de::Deserialize<'de> for ToolUvExtraBuildDependencies {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
struct DependenciesVisitor;
|
||||||
|
|
||||||
|
impl<'de> serde::de::Visitor<'de> for DependenciesVisitor {
|
||||||
|
type Value = ToolUvExtraBuildDependencies;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("a map with unique keys")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
|
||||||
|
where
|
||||||
|
M: serde::de::MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut groups = BTreeMap::new();
|
||||||
|
while let Some((key, value)) = access
|
||||||
|
.next_entry::<PackageName, Vec<uv_pep508::Requirement<VerbatimParsedUrl>>>()?
|
||||||
|
{
|
||||||
|
match groups.entry(key) {
|
||||||
|
std::collections::btree_map::Entry::Occupied(entry) => {
|
||||||
|
return Err(serde::de::Error::custom(format!(
|
||||||
|
"duplicate extra-build-dependencies for `{}`",
|
||||||
|
entry.key()
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
std::collections::btree_map::Entry::Vacant(entry) => {
|
||||||
|
entry.insert(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(ToolUvExtraBuildDependencies(groups))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_map(DependenciesVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, OptionsMetadata, Default, Debug, Clone, PartialEq, Eq)]
|
#[derive(Deserialize, OptionsMetadata, Default, Debug, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(test, derive(Serialize))]
|
#[cfg_attr(test, derive(Serialize))]
|
||||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||||
|
|
|
||||||
|
|
@ -1970,6 +1970,7 @@ mod tests {
|
||||||
"package": null,
|
"package": null,
|
||||||
"default-groups": null,
|
"default-groups": null,
|
||||||
"dependency-groups": null,
|
"dependency-groups": null,
|
||||||
|
"extra-build-dependencies": null,
|
||||||
"dev-dependencies": null,
|
"dev-dependencies": null,
|
||||||
"override-dependencies": null,
|
"override-dependencies": null,
|
||||||
"constraint-dependencies": null,
|
"constraint-dependencies": null,
|
||||||
|
|
@ -2070,6 +2071,7 @@ mod tests {
|
||||||
"package": null,
|
"package": null,
|
||||||
"default-groups": null,
|
"default-groups": null,
|
||||||
"dependency-groups": null,
|
"dependency-groups": null,
|
||||||
|
"extra-build-dependencies": null,
|
||||||
"dev-dependencies": null,
|
"dev-dependencies": null,
|
||||||
"override-dependencies": null,
|
"override-dependencies": null,
|
||||||
"constraint-dependencies": null,
|
"constraint-dependencies": null,
|
||||||
|
|
@ -2283,6 +2285,7 @@ mod tests {
|
||||||
"package": null,
|
"package": null,
|
||||||
"default-groups": null,
|
"default-groups": null,
|
||||||
"dependency-groups": null,
|
"dependency-groups": null,
|
||||||
|
"extra-build-dependencies": null,
|
||||||
"dev-dependencies": null,
|
"dev-dependencies": null,
|
||||||
"override-dependencies": null,
|
"override-dependencies": null,
|
||||||
"constraint-dependencies": null,
|
"constraint-dependencies": null,
|
||||||
|
|
@ -2392,6 +2395,7 @@ mod tests {
|
||||||
"package": null,
|
"package": null,
|
||||||
"default-groups": null,
|
"default-groups": null,
|
||||||
"dependency-groups": null,
|
"dependency-groups": null,
|
||||||
|
"extra-build-dependencies": null,
|
||||||
"dev-dependencies": null,
|
"dev-dependencies": null,
|
||||||
"override-dependencies": null,
|
"override-dependencies": null,
|
||||||
"constraint-dependencies": null,
|
"constraint-dependencies": null,
|
||||||
|
|
@ -2514,6 +2518,7 @@ mod tests {
|
||||||
"package": null,
|
"package": null,
|
||||||
"default-groups": null,
|
"default-groups": null,
|
||||||
"dependency-groups": null,
|
"dependency-groups": null,
|
||||||
|
"extra-build-dependencies": null,
|
||||||
"dev-dependencies": null,
|
"dev-dependencies": null,
|
||||||
"override-dependencies": null,
|
"override-dependencies": null,
|
||||||
"constraint-dependencies": null,
|
"constraint-dependencies": null,
|
||||||
|
|
@ -2610,6 +2615,7 @@ mod tests {
|
||||||
"package": null,
|
"package": null,
|
||||||
"default-groups": null,
|
"default-groups": null,
|
||||||
"dependency-groups": null,
|
"dependency-groups": null,
|
||||||
|
"extra-build-dependencies": null,
|
||||||
"dev-dependencies": null,
|
"dev-dependencies": null,
|
||||||
"override-dependencies": null,
|
"override-dependencies": null,
|
||||||
"constraint-dependencies": null,
|
"constraint-dependencies": null,
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ use uv_requirements::RequirementsSource;
|
||||||
use uv_resolver::{ExcludeNewer, FlatIndex, Preferences};
|
use uv_resolver::{ExcludeNewer, FlatIndex, Preferences};
|
||||||
use uv_settings::PythonInstallMirrors;
|
use uv_settings::PythonInstallMirrors;
|
||||||
use uv_types::{AnyErrorBuild, BuildContext, BuildIsolation, BuildStack, HashStrategy};
|
use uv_types::{AnyErrorBuild, BuildContext, BuildIsolation, BuildStack, HashStrategy};
|
||||||
|
use uv_workspace::pyproject::ExtraBuildDependencies;
|
||||||
use uv_workspace::{DiscoveryOptions, Workspace, WorkspaceCache, WorkspaceError};
|
use uv_workspace::{DiscoveryOptions, Workspace, WorkspaceCache, WorkspaceError};
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
|
|
@ -200,6 +201,7 @@ async fn build_impl(
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
link_mode,
|
link_mode,
|
||||||
upgrade: _,
|
upgrade: _,
|
||||||
|
|
@ -347,6 +349,7 @@ async fn build_impl(
|
||||||
build_constraints,
|
build_constraints,
|
||||||
*no_build_isolation,
|
*no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
*index_strategy,
|
*index_strategy,
|
||||||
*keyring_provider,
|
*keyring_provider,
|
||||||
*exclude_newer,
|
*exclude_newer,
|
||||||
|
|
@ -425,6 +428,7 @@ async fn build_package(
|
||||||
build_constraints: &[RequirementsSource],
|
build_constraints: &[RequirementsSource],
|
||||||
no_build_isolation: bool,
|
no_build_isolation: bool,
|
||||||
no_build_isolation_package: &[PackageName],
|
no_build_isolation_package: &[PackageName],
|
||||||
|
extra_build_dependencies: &ExtraBuildDependencies,
|
||||||
index_strategy: IndexStrategy,
|
index_strategy: IndexStrategy,
|
||||||
keyring_provider: KeyringProviderType,
|
keyring_provider: KeyringProviderType,
|
||||||
exclude_newer: Option<ExcludeNewer>,
|
exclude_newer: Option<ExcludeNewer>,
|
||||||
|
|
@ -561,6 +565,8 @@ async fn build_package(
|
||||||
let workspace_cache = WorkspaceCache::default();
|
let workspace_cache = WorkspaceCache::default();
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
|
let extra_build_requires =
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(extra_build_dependencies.clone());
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
cache,
|
cache,
|
||||||
|
|
@ -574,6 +580,7 @@ async fn build_package(
|
||||||
config_setting,
|
config_setting,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
link_mode,
|
link_mode,
|
||||||
build_options,
|
build_options,
|
||||||
&hasher,
|
&hasher,
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ use uv_cache::Cache;
|
||||||
use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
|
use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
|
||||||
use uv_configuration::{
|
use uv_configuration::{
|
||||||
BuildOptions, Concurrency, ConfigSettings, Constraints, ExportFormat, ExtrasSpecification,
|
BuildOptions, Concurrency, ConfigSettings, Constraints, ExportFormat, ExtrasSpecification,
|
||||||
IndexStrategy, NoBinary, NoBuild, PackageConfigSettings, Preview, Reinstall, SourceStrategy,
|
IndexStrategy, NoBinary, NoBuild, PackageConfigSettings, Preview, PreviewFeatures, Reinstall,
|
||||||
Upgrade,
|
SourceStrategy, Upgrade,
|
||||||
};
|
};
|
||||||
use uv_configuration::{KeyringProviderType, TargetTriple};
|
use uv_configuration::{KeyringProviderType, TargetTriple};
|
||||||
use uv_dispatch::{BuildDispatch, SharedState};
|
use uv_dispatch::{BuildDispatch, SharedState};
|
||||||
|
|
@ -44,8 +44,9 @@ use uv_resolver::{
|
||||||
};
|
};
|
||||||
use uv_torch::{TorchMode, TorchStrategy};
|
use uv_torch::{TorchMode, TorchStrategy};
|
||||||
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy};
|
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy};
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::{warn_user, warn_user_once};
|
||||||
use uv_workspace::WorkspaceCache;
|
use uv_workspace::WorkspaceCache;
|
||||||
|
use uv_workspace::pyproject::ExtraBuildDependencies;
|
||||||
|
|
||||||
use crate::commands::pip::loggers::DefaultResolveLogger;
|
use crate::commands::pip::loggers::DefaultResolveLogger;
|
||||||
use crate::commands::pip::{operations, resolution_environment};
|
use crate::commands::pip::{operations, resolution_environment};
|
||||||
|
|
@ -95,6 +96,7 @@ pub(crate) async fn pip_compile(
|
||||||
config_settings_package: PackageConfigSettings,
|
config_settings_package: PackageConfigSettings,
|
||||||
no_build_isolation: bool,
|
no_build_isolation: bool,
|
||||||
no_build_isolation_package: Vec<PackageName>,
|
no_build_isolation_package: Vec<PackageName>,
|
||||||
|
extra_build_dependencies: &ExtraBuildDependencies,
|
||||||
build_options: BuildOptions,
|
build_options: BuildOptions,
|
||||||
mut python_version: Option<PythonVersion>,
|
mut python_version: Option<PythonVersion>,
|
||||||
python_platform: Option<TargetTriple>,
|
python_platform: Option<TargetTriple>,
|
||||||
|
|
@ -112,6 +114,15 @@ pub(crate) async fn pip_compile(
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
preview: Preview,
|
preview: Preview,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
|
if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES)
|
||||||
|
&& !extra_build_dependencies.is_empty()
|
||||||
|
{
|
||||||
|
warn_user_once!(
|
||||||
|
"The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// If the user provides a `pyproject.toml` or other TOML file as the output file, raise an
|
// If the user provides a `pyproject.toml` or other TOML file as the output file, raise an
|
||||||
// error.
|
// error.
|
||||||
if output_file
|
if output_file
|
||||||
|
|
@ -469,6 +480,8 @@ pub(crate) async fn pip_compile(
|
||||||
.map(|constraint| constraint.requirement.clone()),
|
.map(|constraint| constraint.requirement.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let extra_build_requires =
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(extra_build_dependencies.clone());
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
&cache,
|
&cache,
|
||||||
|
|
@ -482,6 +495,7 @@ pub(crate) async fn pip_compile(
|
||||||
&config_settings,
|
&config_settings,
|
||||||
&config_settings_package,
|
&config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
link_mode,
|
link_mode,
|
||||||
&build_options,
|
&build_options,
|
||||||
&build_hashes,
|
&build_hashes,
|
||||||
|
|
|
||||||
|
|
@ -36,8 +36,9 @@ use uv_resolver::{
|
||||||
};
|
};
|
||||||
use uv_torch::{TorchMode, TorchStrategy};
|
use uv_torch::{TorchMode, TorchStrategy};
|
||||||
use uv_types::{BuildIsolation, HashStrategy};
|
use uv_types::{BuildIsolation, HashStrategy};
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::{warn_user, warn_user_once};
|
||||||
use uv_workspace::WorkspaceCache;
|
use uv_workspace::WorkspaceCache;
|
||||||
|
use uv_workspace::pyproject::ExtraBuildDependencies;
|
||||||
|
|
||||||
use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger, InstallLogger};
|
use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger, InstallLogger};
|
||||||
use crate::commands::pip::operations::Modifications;
|
use crate::commands::pip::operations::Modifications;
|
||||||
|
|
@ -78,6 +79,7 @@ pub(crate) async fn pip_install(
|
||||||
config_settings_package: &PackageConfigSettings,
|
config_settings_package: &PackageConfigSettings,
|
||||||
no_build_isolation: bool,
|
no_build_isolation: bool,
|
||||||
no_build_isolation_package: Vec<PackageName>,
|
no_build_isolation_package: Vec<PackageName>,
|
||||||
|
extra_build_dependencies: &ExtraBuildDependencies,
|
||||||
build_options: BuildOptions,
|
build_options: BuildOptions,
|
||||||
modifications: Modifications,
|
modifications: Modifications,
|
||||||
python_version: Option<PythonVersion>,
|
python_version: Option<PythonVersion>,
|
||||||
|
|
@ -99,6 +101,15 @@ pub(crate) async fn pip_install(
|
||||||
) -> anyhow::Result<ExitStatus> {
|
) -> anyhow::Result<ExitStatus> {
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
|
if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES)
|
||||||
|
&& !extra_build_dependencies.is_empty()
|
||||||
|
{
|
||||||
|
warn_user_once!(
|
||||||
|
"The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
.retries_from_env()?
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
|
|
@ -413,6 +424,8 @@ pub(crate) async fn pip_install(
|
||||||
let state = SharedState::default();
|
let state = SharedState::default();
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
|
let extra_build_requires =
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(extra_build_dependencies.clone());
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
&cache,
|
&cache,
|
||||||
|
|
@ -426,6 +439,7 @@ pub(crate) async fn pip_install(
|
||||||
config_settings,
|
config_settings,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
link_mode,
|
link_mode,
|
||||||
&build_options,
|
&build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,9 @@ use uv_resolver::{
|
||||||
};
|
};
|
||||||
use uv_torch::{TorchMode, TorchStrategy};
|
use uv_torch::{TorchMode, TorchStrategy};
|
||||||
use uv_types::{BuildIsolation, HashStrategy};
|
use uv_types::{BuildIsolation, HashStrategy};
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::{warn_user, warn_user_once};
|
||||||
use uv_workspace::WorkspaceCache;
|
use uv_workspace::WorkspaceCache;
|
||||||
|
use uv_workspace::pyproject::ExtraBuildDependencies;
|
||||||
|
|
||||||
use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger};
|
use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger};
|
||||||
use crate::commands::pip::operations::Modifications;
|
use crate::commands::pip::operations::Modifications;
|
||||||
|
|
@ -67,6 +68,7 @@ pub(crate) async fn pip_sync(
|
||||||
config_settings_package: &PackageConfigSettings,
|
config_settings_package: &PackageConfigSettings,
|
||||||
no_build_isolation: bool,
|
no_build_isolation: bool,
|
||||||
no_build_isolation_package: Vec<PackageName>,
|
no_build_isolation_package: Vec<PackageName>,
|
||||||
|
extra_build_dependencies: &ExtraBuildDependencies,
|
||||||
build_options: BuildOptions,
|
build_options: BuildOptions,
|
||||||
python_version: Option<PythonVersion>,
|
python_version: Option<PythonVersion>,
|
||||||
python_platform: Option<TargetTriple>,
|
python_platform: Option<TargetTriple>,
|
||||||
|
|
@ -85,6 +87,15 @@ pub(crate) async fn pip_sync(
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
preview: Preview,
|
preview: Preview,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
|
if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES)
|
||||||
|
&& !extra_build_dependencies.is_empty()
|
||||||
|
{
|
||||||
|
warn_user_once!(
|
||||||
|
"The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
.retries_from_env()?
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
|
|
@ -348,6 +359,8 @@ pub(crate) async fn pip_sync(
|
||||||
let state = SharedState::default();
|
let state = SharedState::default();
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
|
let extra_build_requires =
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(extra_build_dependencies.clone());
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
&cache,
|
&cache,
|
||||||
|
|
@ -361,6 +374,7 @@ pub(crate) async fn pip_sync(
|
||||||
config_settings,
|
config_settings,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
link_mode,
|
link_mode,
|
||||||
&build_options,
|
&build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,15 @@ pub(crate) async fn add(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES)
|
||||||
|
&& !settings.resolver.extra_build_dependencies.is_empty()
|
||||||
|
{
|
||||||
|
warn_user_once!(
|
||||||
|
"The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
for source in &requirements {
|
for source in &requirements {
|
||||||
match source {
|
match source {
|
||||||
RequirementsSource::PyprojectToml(_) => {
|
RequirementsSource::PyprojectToml(_) => {
|
||||||
|
|
@ -457,6 +466,18 @@ pub(crate) async fn add(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
|
let extra_build_requires = if let AddTarget::Project(project, _) = &target {
|
||||||
|
uv_distribution::ExtraBuildRequires::from_workspace(
|
||||||
|
settings.resolver.extra_build_dependencies.clone(),
|
||||||
|
project.workspace(),
|
||||||
|
&settings.resolver.index_locations,
|
||||||
|
settings.resolver.sources,
|
||||||
|
)?
|
||||||
|
} else {
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(
|
||||||
|
settings.resolver.extra_build_dependencies.clone(),
|
||||||
|
)
|
||||||
|
};
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
cache,
|
cache,
|
||||||
|
|
@ -470,6 +491,7 @@ pub(crate) async fn add(
|
||||||
&settings.resolver.config_setting,
|
&settings.resolver.config_setting,
|
||||||
&settings.resolver.config_settings_package,
|
&settings.resolver.config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
settings.resolver.link_mode,
|
settings.resolver.link_mode,
|
||||||
&settings.resolver.build_options,
|
&settings.resolver.build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
@ -1312,6 +1334,7 @@ impl PythonTarget {
|
||||||
|
|
||||||
/// Represents the destination where dependencies are added, either to a project or a script.
|
/// Represents the destination where dependencies are added, either to a project or a script.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub(super) enum AddTarget {
|
pub(super) enum AddTarget {
|
||||||
/// A PEP 723 script, with inline metadata.
|
/// A PEP 723 script, with inline metadata.
|
||||||
Script(Pep723Script, Box<Interpreter>),
|
Script(Pep723Script, Box<Interpreter>),
|
||||||
|
|
@ -1420,6 +1443,7 @@ impl AddTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
enum AddTargetSnapshot {
|
enum AddTargetSnapshot {
|
||||||
Script(Pep723Script, Option<Vec<u8>>),
|
Script(Pep723Script, Option<Vec<u8>>),
|
||||||
Project(VirtualProject, Option<Vec<u8>>),
|
Project(VirtualProject, Option<Vec<u8>>),
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ use crate::printer::Printer;
|
||||||
use crate::settings::{NetworkSettings, ResolverSettings};
|
use crate::settings::{NetworkSettings, ResolverSettings};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
enum ExportTarget {
|
enum ExportTarget {
|
||||||
/// A PEP 723 script, with inline metadata.
|
/// A PEP 723 script, with inline metadata.
|
||||||
Script(Pep723Script),
|
Script(Pep723Script),
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ use crate::commands::pip::loggers::{DefaultResolveLogger, ResolveLogger, Summary
|
||||||
use crate::commands::project::lock_target::LockTarget;
|
use crate::commands::project::lock_target::LockTarget;
|
||||||
use crate::commands::project::{
|
use crate::commands::project::{
|
||||||
ProjectError, ProjectInterpreter, ScriptInterpreter, UniversalState,
|
ProjectError, ProjectInterpreter, ScriptInterpreter, UniversalState,
|
||||||
init_script_python_requirement,
|
init_script_python_requirement, script_specification,
|
||||||
};
|
};
|
||||||
use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
|
use crate::commands::reporters::{PythonDownloadReporter, ResolverReporter};
|
||||||
use crate::commands::{ExitStatus, ScriptPath, diagnostics, pip};
|
use crate::commands::{ExitStatus, ScriptPath, diagnostics, pip};
|
||||||
|
|
@ -435,6 +435,7 @@ async fn do_lock(
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
link_mode,
|
link_mode,
|
||||||
upgrade,
|
upgrade,
|
||||||
|
|
@ -453,6 +454,15 @@ async fn do_lock(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES)
|
||||||
|
&& !extra_build_dependencies.is_empty()
|
||||||
|
{
|
||||||
|
warn_user_once!(
|
||||||
|
"The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Collect the requirements, etc.
|
// Collect the requirements, etc.
|
||||||
let members = target.members();
|
let members = target.members();
|
||||||
let packages = target.packages();
|
let packages = target.packages();
|
||||||
|
|
@ -695,6 +705,24 @@ async fn do_lock(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
|
let extra_build_requires = match &target {
|
||||||
|
LockTarget::Workspace(workspace) => uv_distribution::ExtraBuildRequires::from_workspace(
|
||||||
|
extra_build_dependencies.clone(),
|
||||||
|
workspace,
|
||||||
|
index_locations,
|
||||||
|
*sources,
|
||||||
|
)?,
|
||||||
|
LockTarget::Script(script) => {
|
||||||
|
// Try to get extra build dependencies from the script metadata
|
||||||
|
script_specification(Pep723ItemRef::Script(script), settings)?
|
||||||
|
.map(|spec| spec.extra_build_requires)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(
|
||||||
|
extra_build_dependencies.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
cache,
|
cache,
|
||||||
|
|
@ -708,6 +736,7 @@ async fn do_lock(
|
||||||
config_setting,
|
config_setting,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
*link_mode,
|
*link_mode,
|
||||||
build_options,
|
build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy};
|
||||||
use uv_virtualenv::remove_virtualenv;
|
use uv_virtualenv::remove_virtualenv;
|
||||||
use uv_warnings::{warn_user, warn_user_once};
|
use uv_warnings::{warn_user, warn_user_once};
|
||||||
use uv_workspace::dependency_groups::DependencyGroupError;
|
use uv_workspace::dependency_groups::DependencyGroupError;
|
||||||
|
use uv_workspace::pyproject::ExtraBuildDependencies;
|
||||||
use uv_workspace::pyproject::PyProjectToml;
|
use uv_workspace::pyproject::PyProjectToml;
|
||||||
use uv_workspace::{RequiresPythonSources, Workspace, WorkspaceCache};
|
use uv_workspace::{RequiresPythonSources, Workspace, WorkspaceCache};
|
||||||
|
|
||||||
|
|
@ -1692,6 +1693,7 @@ pub(crate) async fn resolve_names(
|
||||||
link_mode,
|
link_mode,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
prerelease: _,
|
prerelease: _,
|
||||||
resolution: _,
|
resolution: _,
|
||||||
sources,
|
sources,
|
||||||
|
|
@ -1741,6 +1743,8 @@ pub(crate) async fn resolve_names(
|
||||||
let build_hasher = HashStrategy::default();
|
let build_hasher = HashStrategy::default();
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
|
let extra_build_requires =
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(extra_build_dependencies.clone());
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
cache,
|
cache,
|
||||||
|
|
@ -1754,6 +1758,7 @@ pub(crate) async fn resolve_names(
|
||||||
config_setting,
|
config_setting,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
*link_mode,
|
*link_mode,
|
||||||
build_options,
|
build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
@ -1847,6 +1852,7 @@ pub(crate) async fn resolve_environment(
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
link_mode,
|
link_mode,
|
||||||
upgrade: _,
|
upgrade: _,
|
||||||
|
|
@ -1951,6 +1957,8 @@ pub(crate) async fn resolve_environment(
|
||||||
let workspace_cache = WorkspaceCache::default();
|
let workspace_cache = WorkspaceCache::default();
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
|
let extra_build_requires =
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(extra_build_dependencies.clone());
|
||||||
let resolve_dispatch = BuildDispatch::new(
|
let resolve_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
cache,
|
cache,
|
||||||
|
|
@ -1964,6 +1972,7 @@ pub(crate) async fn resolve_environment(
|
||||||
config_setting,
|
config_setting,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
*link_mode,
|
*link_mode,
|
||||||
build_options,
|
build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
@ -2032,6 +2041,7 @@ pub(crate) async fn sync_environment(
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
link_mode,
|
link_mode,
|
||||||
compile_bytecode,
|
compile_bytecode,
|
||||||
|
|
@ -2091,6 +2101,8 @@ pub(crate) async fn sync_environment(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a build dispatch.
|
// Create a build dispatch.
|
||||||
|
let extra_build_requires =
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(extra_build_dependencies.clone());
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
cache,
|
cache,
|
||||||
|
|
@ -2104,6 +2116,7 @@ pub(crate) async fn sync_environment(
|
||||||
config_setting,
|
config_setting,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
link_mode,
|
link_mode,
|
||||||
build_options,
|
build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
@ -2148,6 +2161,15 @@ pub(crate) async fn sync_environment(
|
||||||
Ok(venv)
|
Ok(venv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A script specification that includes both requirements and extra build dependencies.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct ScriptSpecification {
|
||||||
|
/// The requirements specification for the script.
|
||||||
|
pub(crate) requirements: RequirementsSpecification,
|
||||||
|
/// The extra build dependencies for the script.
|
||||||
|
pub(crate) extra_build_requires: uv_distribution::ExtraBuildRequires,
|
||||||
|
}
|
||||||
|
|
||||||
/// The result of updating a [`PythonEnvironment`] to satisfy a set of [`RequirementsSource`]s.
|
/// The result of updating a [`PythonEnvironment`] to satisfy a set of [`RequirementsSource`]s.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct EnvironmentUpdate {
|
pub(crate) struct EnvironmentUpdate {
|
||||||
|
|
@ -2170,6 +2192,7 @@ pub(crate) async fn update_environment(
|
||||||
spec: RequirementsSpecification,
|
spec: RequirementsSpecification,
|
||||||
modifications: Modifications,
|
modifications: Modifications,
|
||||||
build_constraints: Constraints,
|
build_constraints: Constraints,
|
||||||
|
extra_build_requires: uv_distribution::ExtraBuildRequires,
|
||||||
settings: &ResolverInstallerSettings,
|
settings: &ResolverInstallerSettings,
|
||||||
network_settings: &NetworkSettings,
|
network_settings: &NetworkSettings,
|
||||||
state: &SharedState,
|
state: &SharedState,
|
||||||
|
|
@ -2200,6 +2223,7 @@ pub(crate) async fn update_environment(
|
||||||
link_mode,
|
link_mode,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies: _,
|
||||||
prerelease,
|
prerelease,
|
||||||
resolution,
|
resolution,
|
||||||
sources,
|
sources,
|
||||||
|
|
@ -2330,6 +2354,7 @@ pub(crate) async fn update_environment(
|
||||||
config_setting,
|
config_setting,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
*link_mode,
|
*link_mode,
|
||||||
build_options,
|
build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
@ -2535,12 +2560,12 @@ pub(crate) fn detect_conflicts(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine the [`RequirementsSpecification`] for a script.
|
/// Determine the [`ScriptSpecification`] for a script.
|
||||||
#[allow(clippy::result_large_err)]
|
#[allow(clippy::result_large_err)]
|
||||||
pub(crate) fn script_specification(
|
pub(crate) fn script_specification(
|
||||||
script: Pep723ItemRef<'_>,
|
script: Pep723ItemRef<'_>,
|
||||||
settings: &ResolverSettings,
|
settings: &ResolverSettings,
|
||||||
) -> Result<Option<RequirementsSpecification>, ProjectError> {
|
) -> Result<Option<ScriptSpecification>, ProjectError> {
|
||||||
let Some(dependencies) = script.metadata().dependencies.as_ref() else {
|
let Some(dependencies) = script.metadata().dependencies.as_ref() else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
@ -2635,11 +2660,47 @@ pub(crate) fn script_specification(
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Ok(Some(RequirementsSpecification::from_overrides(
|
// Collect any `tool.uv.extra-build-dependencies` from the script.
|
||||||
|
let empty = BTreeMap::default();
|
||||||
|
let script_extra_build_dependencies = script
|
||||||
|
.metadata()
|
||||||
|
.tool
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|tool| tool.uv.as_ref())
|
||||||
|
.and_then(|uv| uv.extra_build_dependencies.as_ref())
|
||||||
|
.unwrap_or(&empty);
|
||||||
|
|
||||||
|
// Lower the extra build dependencies
|
||||||
|
let mut extra_build_dependencies = ExtraBuildDependencies::default();
|
||||||
|
for (name, requirements) in script_extra_build_dependencies {
|
||||||
|
let lowered_requirements: Vec<_> = requirements
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.flat_map(|requirement| {
|
||||||
|
LoweredRequirement::from_non_workspace_requirement(
|
||||||
|
requirement,
|
||||||
|
script_dir.as_ref(),
|
||||||
|
script_sources,
|
||||||
|
script_indexes,
|
||||||
|
&settings.index_locations,
|
||||||
|
)
|
||||||
|
.map_ok(|req| req.into_inner().into())
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
extra_build_dependencies.insert(name.clone(), lowered_requirements);
|
||||||
|
}
|
||||||
|
|
||||||
|
let extra_build_requires =
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(extra_build_dependencies);
|
||||||
|
|
||||||
|
Ok(Some(ScriptSpecification {
|
||||||
|
requirements: RequirementsSpecification::from_overrides(
|
||||||
requirements,
|
requirements,
|
||||||
constraints,
|
constraints,
|
||||||
overrides,
|
overrides,
|
||||||
)))
|
),
|
||||||
|
extra_build_requires,
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Warn if the user provides (e.g.) an `--index-url` in a requirements file.
|
/// Warn if the user provides (e.g.) an `--index-url` in a requirements file.
|
||||||
|
|
|
||||||
|
|
@ -386,6 +386,7 @@ pub(crate) async fn remove(
|
||||||
|
|
||||||
/// Represents the destination where dependencies are added, either to a project or a script.
|
/// Represents the destination where dependencies are added, either to a project or a script.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
enum RemoveTarget {
|
enum RemoveTarget {
|
||||||
/// A PEP 723 script, with inline metadata.
|
/// A PEP 723 script, with inline metadata.
|
||||||
Project(VirtualProject),
|
Project(VirtualProject),
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,9 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install the script requirements, if necessary. Otherwise, use an isolated environment.
|
// Install the script requirements, if necessary. Otherwise, use an isolated environment.
|
||||||
if let Some(spec) = script_specification((&script).into(), &settings.resolver)? {
|
if let Some(script_spec) = script_specification((&script).into(), &settings.resolver)? {
|
||||||
|
let spec = script_spec.requirements;
|
||||||
|
let script_extra_build_requires = script_spec.extra_build_requires;
|
||||||
let environment = ScriptEnvironment::get_or_init(
|
let environment = ScriptEnvironment::get_or_init(
|
||||||
(&script).into(),
|
(&script).into(),
|
||||||
python.as_deref().map(PythonRequest::parse),
|
python.as_deref().map(PythonRequest::parse),
|
||||||
|
|
@ -407,6 +409,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||||
spec,
|
spec,
|
||||||
modifications,
|
modifications,
|
||||||
build_constraints.unwrap_or_default(),
|
build_constraints.unwrap_or_default(),
|
||||||
|
script_extra_build_requires,
|
||||||
&settings,
|
&settings,
|
||||||
&network_settings,
|
&network_settings,
|
||||||
&sync_state,
|
&sync_state,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use uv_configuration::{
|
||||||
BuildDependencyStrategy, Concurrency, Constraints, DependencyGroups,
|
BuildDependencyStrategy, Concurrency, Constraints, DependencyGroups,
|
||||||
DependencyGroupsWithDefaults, DryRun, EditableMode, ExtrasSpecification,
|
DependencyGroupsWithDefaults, DryRun, EditableMode, ExtrasSpecification,
|
||||||
ExtrasSpecificationWithDefaults, HashCheckingMode, InstallOptions, Preview, PreviewFeatures,
|
ExtrasSpecificationWithDefaults, HashCheckingMode, InstallOptions, Preview, PreviewFeatures,
|
||||||
TargetTriple,
|
TargetTriple, Upgrade,
|
||||||
};
|
};
|
||||||
use uv_dispatch::BuildDispatch;
|
use uv_dispatch::BuildDispatch;
|
||||||
use uv_distribution_types::{
|
use uv_distribution_types::{
|
||||||
|
|
@ -27,12 +27,13 @@ use uv_normalize::{DefaultExtras, DefaultGroups, PackageName};
|
||||||
use uv_pep508::{MarkerTree, VersionOrUrl};
|
use uv_pep508::{MarkerTree, VersionOrUrl};
|
||||||
use uv_pypi_types::{ParsedArchiveUrl, ParsedGitUrl, ParsedUrl};
|
use uv_pypi_types::{ParsedArchiveUrl, ParsedGitUrl, ParsedUrl};
|
||||||
use uv_python::{PythonDownloads, PythonEnvironment, PythonPreference, PythonRequest};
|
use uv_python::{PythonDownloads, PythonEnvironment, PythonPreference, PythonRequest};
|
||||||
use uv_resolver::{FlatIndex, Installable, Lock, Preference, Preferences, ResolverEnvironment};
|
use uv_requirements::RequirementsSpecification;
|
||||||
|
use uv_resolver::{FlatIndex, ForkStrategy, Installable, Lock, Preference, Preferences, PrereleaseMode, ResolutionMode, ResolverEnvironment};
|
||||||
use uv_scripts::{Pep723ItemRef, Pep723Script};
|
use uv_scripts::{Pep723ItemRef, Pep723Script};
|
||||||
use uv_settings::PythonInstallMirrors;
|
use uv_settings::PythonInstallMirrors;
|
||||||
use uv_types::{BuildIsolation, HashStrategy};
|
use uv_types::{BuildIsolation, HashStrategy};
|
||||||
use uv_warnings::{warn_user, warn_user_once};
|
use uv_warnings::{warn_user, warn_user_once};
|
||||||
use uv_workspace::pyproject::Source;
|
use uv_workspace::pyproject::{ExtraBuildDependencies, Source};
|
||||||
use uv_workspace::{DiscoveryOptions, MemberDiscovery, VirtualProject, Workspace, WorkspaceCache};
|
use uv_workspace::{DiscoveryOptions, MemberDiscovery, VirtualProject, Workspace, WorkspaceCache};
|
||||||
|
|
||||||
use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger, InstallLogger};
|
use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger, InstallLogger};
|
||||||
|
|
@ -48,7 +49,9 @@ use crate::commands::project::{
|
||||||
};
|
};
|
||||||
use crate::commands::{ExitStatus, diagnostics};
|
use crate::commands::{ExitStatus, diagnostics};
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
use crate::settings::{InstallerSettingsRef, NetworkSettings, ResolverInstallerSettings};
|
use crate::settings::{
|
||||||
|
InstallerSettingsRef, NetworkSettings, ResolverInstallerSettings, ResolverSettings,
|
||||||
|
};
|
||||||
|
|
||||||
/// Sync the project environment.
|
/// Sync the project environment.
|
||||||
#[allow(clippy::fn_params_excessive_bools)]
|
#[allow(clippy::fn_params_excessive_bools)]
|
||||||
|
|
@ -223,8 +226,18 @@ pub(crate) async fn sync(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the requirements from the script.
|
// Parse the requirements from the script.
|
||||||
let spec = script_specification(Pep723ItemRef::Script(script), &settings.resolver)?
|
let script_spec =
|
||||||
.unwrap_or_default();
|
script_specification(Pep723ItemRef::Script(script), &settings.resolver)?;
|
||||||
|
let (spec, script_extra_build_requires) = if let Some(script_spec) = script_spec {
|
||||||
|
(script_spec.requirements, script_spec.extra_build_requires)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
RequirementsSpecification::default(),
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(
|
||||||
|
ExtraBuildDependencies::default(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
// Parse the build constraints from the script.
|
// Parse the build constraints from the script.
|
||||||
let build_constraints = script
|
let build_constraints = script
|
||||||
|
|
@ -249,6 +262,7 @@ pub(crate) async fn sync(
|
||||||
spec,
|
spec,
|
||||||
modifications,
|
modifications,
|
||||||
build_constraints.unwrap_or_default(),
|
build_constraints.unwrap_or_default(),
|
||||||
|
script_extra_build_requires,
|
||||||
&settings,
|
&settings,
|
||||||
&network_settings,
|
&network_settings,
|
||||||
&PlatformState::default(),
|
&PlatformState::default(),
|
||||||
|
|
@ -495,6 +509,7 @@ fn identify_installation_target<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
enum SyncTarget {
|
enum SyncTarget {
|
||||||
/// Sync a project environment.
|
/// Sync a project environment.
|
||||||
Project(VirtualProject),
|
Project(VirtualProject),
|
||||||
|
|
@ -579,6 +594,7 @@ pub(super) async fn do_sync(
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
exclude_newer,
|
exclude_newer,
|
||||||
link_mode,
|
link_mode,
|
||||||
compile_bytecode,
|
compile_bytecode,
|
||||||
|
|
@ -588,6 +604,57 @@ pub(super) async fn do_sync(
|
||||||
build_dependency_strategy,
|
build_dependency_strategy,
|
||||||
} = settings;
|
} = settings;
|
||||||
|
|
||||||
|
if !preview.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES)
|
||||||
|
&& !extra_build_dependencies.is_empty()
|
||||||
|
{
|
||||||
|
warn_user_once!(
|
||||||
|
"The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lower the extra build dependencies with source resolution
|
||||||
|
let extra_build_requires = match &target {
|
||||||
|
InstallTarget::Workspace { workspace, .. }
|
||||||
|
| InstallTarget::Project { workspace, .. }
|
||||||
|
| InstallTarget::NonProjectWorkspace { workspace, .. } => {
|
||||||
|
uv_distribution::ExtraBuildRequires::from_workspace(
|
||||||
|
extra_build_dependencies.clone(),
|
||||||
|
workspace,
|
||||||
|
index_locations,
|
||||||
|
sources,
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
InstallTarget::Script { script, .. } => {
|
||||||
|
// Try to get extra build dependencies from the script metadata
|
||||||
|
let resolver_settings = ResolverSettings {
|
||||||
|
build_options: build_options.clone(),
|
||||||
|
config_setting: config_setting.clone(),
|
||||||
|
config_settings_package: config_settings_package.clone(),
|
||||||
|
dependency_metadata: dependency_metadata.clone(),
|
||||||
|
exclude_newer,
|
||||||
|
fork_strategy: ForkStrategy::default(),
|
||||||
|
index_locations: index_locations.clone(),
|
||||||
|
index_strategy,
|
||||||
|
keyring_provider,
|
||||||
|
link_mode,
|
||||||
|
no_build_isolation,
|
||||||
|
no_build_isolation_package: no_build_isolation_package.to_vec(),
|
||||||
|
extra_build_dependencies: extra_build_dependencies.clone(),
|
||||||
|
prerelease: PrereleaseMode::default(),
|
||||||
|
resolution: ResolutionMode::default(),
|
||||||
|
sources,
|
||||||
|
upgrade: Upgrade::default(),
|
||||||
|
build_dependency_strategy: *build_dependency_strategy,
|
||||||
|
};
|
||||||
|
script_specification(Pep723ItemRef::Script(script), &resolver_settings)?
|
||||||
|
.map(|spec| spec.extra_build_requires)
|
||||||
|
.unwrap_or_else(|| uv_distribution::ExtraBuildRequires {
|
||||||
|
extra_build_dependencies: ExtraBuildDependencies::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let client_builder = BaseClientBuilder::new()
|
let client_builder = BaseClientBuilder::new()
|
||||||
.retries_from_env()?
|
.retries_from_env()?
|
||||||
.connectivity(network_settings.connectivity)
|
.connectivity(network_settings.connectivity)
|
||||||
|
|
@ -739,6 +806,7 @@ pub(super) async fn do_sync(
|
||||||
config_setting,
|
config_setting,
|
||||||
config_settings_package,
|
config_settings_package,
|
||||||
build_isolation,
|
build_isolation,
|
||||||
|
&extra_build_requires,
|
||||||
link_mode,
|
link_mode,
|
||||||
build_options,
|
build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,7 @@ pub(crate) async fn tree(
|
||||||
config_settings_package: _,
|
config_settings_package: _,
|
||||||
no_build_isolation: _,
|
no_build_isolation: _,
|
||||||
no_build_isolation_package: _,
|
no_build_isolation_package: _,
|
||||||
|
extra_build_dependencies: _,
|
||||||
exclude_newer: _,
|
exclude_newer: _,
|
||||||
link_mode: _,
|
link_mode: _,
|
||||||
upgrade: _,
|
upgrade: _,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ use uv_requirements::{RequirementsSource, RequirementsSpecification};
|
||||||
use uv_settings::{PythonInstallMirrors, ResolverInstallerOptions, ToolOptions};
|
use uv_settings::{PythonInstallMirrors, ResolverInstallerOptions, ToolOptions};
|
||||||
use uv_tool::InstalledTools;
|
use uv_tool::InstalledTools;
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::warn_user;
|
||||||
use uv_workspace::WorkspaceCache;
|
use uv_workspace::{WorkspaceCache, pyproject::ExtraBuildDependencies};
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger};
|
use crate::commands::pip::loggers::{DefaultInstallLogger, DefaultResolveLogger};
|
||||||
|
|
@ -439,6 +439,7 @@ pub(crate) async fn install(
|
||||||
spec,
|
spec,
|
||||||
Modifications::Exact,
|
Modifications::Exact,
|
||||||
Constraints::from_requirements(build_constraints.iter().cloned()),
|
Constraints::from_requirements(build_constraints.iter().cloned()),
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(ExtraBuildDependencies::default()),
|
||||||
&settings,
|
&settings,
|
||||||
&network_settings,
|
&network_settings,
|
||||||
&state,
|
&state,
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ use uv_requirements::RequirementsSpecification;
|
||||||
use uv_settings::{Combine, PythonInstallMirrors, ResolverInstallerOptions, ToolOptions};
|
use uv_settings::{Combine, PythonInstallMirrors, ResolverInstallerOptions, ToolOptions};
|
||||||
use uv_tool::InstalledTools;
|
use uv_tool::InstalledTools;
|
||||||
use uv_warnings::write_error_chain;
|
use uv_warnings::write_error_chain;
|
||||||
use uv_workspace::WorkspaceCache;
|
use uv_workspace::{WorkspaceCache, pyproject::ExtraBuildDependencies};
|
||||||
|
|
||||||
use crate::commands::pip::loggers::{
|
use crate::commands::pip::loggers::{
|
||||||
DefaultInstallLogger, SummaryResolveLogger, UpgradeInstallLogger,
|
DefaultInstallLogger, SummaryResolveLogger, UpgradeInstallLogger,
|
||||||
|
|
@ -337,6 +337,7 @@ async fn upgrade_tool(
|
||||||
spec,
|
spec,
|
||||||
Modifications::Exact,
|
Modifications::Exact,
|
||||||
build_constraints,
|
build_constraints,
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(ExtraBuildDependencies::default()),
|
||||||
&settings,
|
&settings,
|
||||||
network_settings,
|
network_settings,
|
||||||
&state,
|
&state,
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ use uv_shell::{Shell, shlex_posix, shlex_windows};
|
||||||
use uv_types::{AnyErrorBuild, BuildContext, BuildIsolation, BuildStack, HashStrategy};
|
use uv_types::{AnyErrorBuild, BuildContext, BuildIsolation, BuildStack, HashStrategy};
|
||||||
use uv_virtualenv::OnExisting;
|
use uv_virtualenv::OnExisting;
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::warn_user;
|
||||||
|
use uv_workspace::pyproject::ExtraBuildDependencies;
|
||||||
use uv_workspace::{DiscoveryOptions, VirtualProject, WorkspaceCache, WorkspaceError};
|
use uv_workspace::{DiscoveryOptions, VirtualProject, WorkspaceCache, WorkspaceError};
|
||||||
|
|
||||||
use crate::commands::ExitStatus;
|
use crate::commands::ExitStatus;
|
||||||
|
|
@ -266,7 +267,8 @@ pub(crate) async fn venv(
|
||||||
|
|
||||||
// Do not allow builds
|
// Do not allow builds
|
||||||
let build_options = BuildOptions::new(NoBinary::None, NoBuild::All);
|
let build_options = BuildOptions::new(NoBinary::None, NoBuild::All);
|
||||||
|
let extra_build_requires =
|
||||||
|
uv_distribution::ExtraBuildRequires::from_lowered(ExtraBuildDependencies::default());
|
||||||
// Prep the build context.
|
// Prep the build context.
|
||||||
let build_dispatch = BuildDispatch::new(
|
let build_dispatch = BuildDispatch::new(
|
||||||
&client,
|
&client,
|
||||||
|
|
@ -281,6 +283,7 @@ pub(crate) async fn venv(
|
||||||
&config_settings,
|
&config_settings,
|
||||||
&config_settings_package,
|
&config_settings_package,
|
||||||
BuildIsolation::Isolated,
|
BuildIsolation::Isolated,
|
||||||
|
&extra_build_requires,
|
||||||
link_mode,
|
link_mode,
|
||||||
&build_options,
|
&build_options,
|
||||||
&build_hasher,
|
&build_hasher,
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ use uv_cli::{
|
||||||
ProjectCommand, PythonCommand, PythonNamespace, SelfCommand, SelfNamespace, ToolCommand,
|
ProjectCommand, PythonCommand, PythonNamespace, SelfCommand, SelfNamespace, ToolCommand,
|
||||||
ToolNamespace, TopLevelArgs, compat::CompatArgs,
|
ToolNamespace, TopLevelArgs, compat::CompatArgs,
|
||||||
};
|
};
|
||||||
use uv_configuration::min_stack_size;
|
use uv_configuration::{PreviewFeatures, min_stack_size};
|
||||||
use uv_fs::{CWD, Simplified};
|
use uv_fs::{CWD, Simplified};
|
||||||
#[cfg(feature = "self-update")]
|
#[cfg(feature = "self-update")]
|
||||||
use uv_pep440::release_specifiers_to_ranges;
|
use uv_pep440::release_specifiers_to_ranges;
|
||||||
|
|
@ -443,6 +443,16 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
// Resolve the settings from the command-line arguments and workspace configuration.
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
||||||
let args = PipCompileSettings::resolve(args, filesystem);
|
let args = PipCompileSettings::resolve(args, filesystem);
|
||||||
show_settings!(args);
|
show_settings!(args);
|
||||||
|
if !args.settings.extra_build_dependencies.is_empty()
|
||||||
|
&& !globals
|
||||||
|
.preview
|
||||||
|
.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES)
|
||||||
|
{
|
||||||
|
warn_user_once!(
|
||||||
|
"The `extra-build-dependencies` setting is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize the cache.
|
// Initialize the cache.
|
||||||
let cache = cache.init()?.with_refresh(
|
let cache = cache.init()?.with_refresh(
|
||||||
|
|
@ -516,6 +526,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
args.settings.config_settings_package,
|
args.settings.config_settings_package,
|
||||||
args.settings.no_build_isolation,
|
args.settings.no_build_isolation,
|
||||||
args.settings.no_build_isolation_package,
|
args.settings.no_build_isolation_package,
|
||||||
|
&args.settings.extra_build_dependencies,
|
||||||
args.settings.build_options,
|
args.settings.build_options,
|
||||||
args.settings.python_version,
|
args.settings.python_version,
|
||||||
args.settings.python_platform,
|
args.settings.python_platform,
|
||||||
|
|
@ -543,6 +554,16 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
// Resolve the settings from the command-line arguments and workspace configuration.
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
||||||
let args = PipSyncSettings::resolve(args, filesystem);
|
let args = PipSyncSettings::resolve(args, filesystem);
|
||||||
show_settings!(args);
|
show_settings!(args);
|
||||||
|
if !args.settings.extra_build_dependencies.is_empty()
|
||||||
|
&& !globals
|
||||||
|
.preview
|
||||||
|
.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES)
|
||||||
|
{
|
||||||
|
warn_user_once!(
|
||||||
|
"The `extra-build-dependencies` setting is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize the cache.
|
// Initialize the cache.
|
||||||
let cache = cache.init()?.with_refresh(
|
let cache = cache.init()?.with_refresh(
|
||||||
|
|
@ -593,6 +614,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
&args.settings.config_settings_package,
|
&args.settings.config_settings_package,
|
||||||
args.settings.no_build_isolation,
|
args.settings.no_build_isolation,
|
||||||
args.settings.no_build_isolation_package,
|
args.settings.no_build_isolation_package,
|
||||||
|
&args.settings.extra_build_dependencies,
|
||||||
args.settings.build_options,
|
args.settings.build_options,
|
||||||
args.settings.python_version,
|
args.settings.python_version,
|
||||||
args.settings.python_platform,
|
args.settings.python_platform,
|
||||||
|
|
@ -621,6 +643,16 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
// Resolve the settings from the command-line arguments and workspace configuration.
|
// Resolve the settings from the command-line arguments and workspace configuration.
|
||||||
let mut args = PipInstallSettings::resolve(args, filesystem);
|
let mut args = PipInstallSettings::resolve(args, filesystem);
|
||||||
show_settings!(args);
|
show_settings!(args);
|
||||||
|
if !args.settings.extra_build_dependencies.is_empty()
|
||||||
|
&& !globals
|
||||||
|
.preview
|
||||||
|
.is_enabled(PreviewFeatures::EXTRA_BUILD_DEPENDENCIES)
|
||||||
|
{
|
||||||
|
warn_user_once!(
|
||||||
|
"The `extra-build-dependencies` setting is experimental and may change without warning. Pass `--preview-features {}` to disable this warning.",
|
||||||
|
PreviewFeatures::EXTRA_BUILD_DEPENDENCIES
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let mut requirements = Vec::with_capacity(
|
let mut requirements = Vec::with_capacity(
|
||||||
args.package.len() + args.editables.len() + args.requirements.len(),
|
args.package.len() + args.editables.len() + args.requirements.len(),
|
||||||
|
|
@ -735,6 +767,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
&args.settings.config_settings_package,
|
&args.settings.config_settings_package,
|
||||||
args.settings.no_build_isolation,
|
args.settings.no_build_isolation,
|
||||||
args.settings.no_build_isolation_package,
|
args.settings.no_build_isolation_package,
|
||||||
|
&args.settings.extra_build_dependencies,
|
||||||
args.settings.build_options,
|
args.settings.build_options,
|
||||||
args.modifications,
|
args.modifications,
|
||||||
args.settings.python_version,
|
args.settings.python_version,
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ use uv_settings::{
|
||||||
use uv_static::EnvVars;
|
use uv_static::EnvVars;
|
||||||
use uv_torch::TorchMode;
|
use uv_torch::TorchMode;
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::warn_user_once;
|
||||||
use uv_workspace::pyproject::DependencyType;
|
use uv_workspace::pyproject::{DependencyType, ExtraBuildDependencies};
|
||||||
use uv_workspace::pyproject_mut::AddBoundsKind;
|
use uv_workspace::pyproject_mut::AddBoundsKind;
|
||||||
|
|
||||||
use crate::commands::ToolRunCommand;
|
use crate::commands::ToolRunCommand;
|
||||||
|
|
@ -2708,6 +2708,7 @@ pub(crate) struct InstallerSettingsRef<'a> {
|
||||||
pub(crate) config_settings_package: &'a PackageConfigSettings,
|
pub(crate) config_settings_package: &'a PackageConfigSettings,
|
||||||
pub(crate) no_build_isolation: bool,
|
pub(crate) no_build_isolation: bool,
|
||||||
pub(crate) no_build_isolation_package: &'a [PackageName],
|
pub(crate) no_build_isolation_package: &'a [PackageName],
|
||||||
|
pub(crate) extra_build_dependencies: &'a ExtraBuildDependencies,
|
||||||
pub(crate) exclude_newer: Option<ExcludeNewer>,
|
pub(crate) exclude_newer: Option<ExcludeNewer>,
|
||||||
pub(crate) link_mode: LinkMode,
|
pub(crate) link_mode: LinkMode,
|
||||||
pub(crate) compile_bytecode: bool,
|
pub(crate) compile_bytecode: bool,
|
||||||
|
|
@ -2735,6 +2736,7 @@ pub(crate) struct ResolverSettings {
|
||||||
pub(crate) link_mode: LinkMode,
|
pub(crate) link_mode: LinkMode,
|
||||||
pub(crate) no_build_isolation: bool,
|
pub(crate) no_build_isolation: bool,
|
||||||
pub(crate) no_build_isolation_package: Vec<PackageName>,
|
pub(crate) no_build_isolation_package: Vec<PackageName>,
|
||||||
|
pub(crate) extra_build_dependencies: ExtraBuildDependencies,
|
||||||
pub(crate) prerelease: PrereleaseMode,
|
pub(crate) prerelease: PrereleaseMode,
|
||||||
pub(crate) resolution: ResolutionMode,
|
pub(crate) resolution: ResolutionMode,
|
||||||
pub(crate) sources: SourceStrategy,
|
pub(crate) sources: SourceStrategy,
|
||||||
|
|
@ -2788,6 +2790,7 @@ impl From<ResolverOptions> for ResolverSettings {
|
||||||
config_settings_package: value.config_settings_package.unwrap_or_default(),
|
config_settings_package: value.config_settings_package.unwrap_or_default(),
|
||||||
no_build_isolation: value.no_build_isolation.unwrap_or_default(),
|
no_build_isolation: value.no_build_isolation.unwrap_or_default(),
|
||||||
no_build_isolation_package: value.no_build_isolation_package.unwrap_or_default(),
|
no_build_isolation_package: value.no_build_isolation_package.unwrap_or_default(),
|
||||||
|
extra_build_dependencies: value.extra_build_dependencies.unwrap_or_default(),
|
||||||
exclude_newer: value.exclude_newer,
|
exclude_newer: value.exclude_newer,
|
||||||
link_mode: value.link_mode.unwrap_or_default(),
|
link_mode: value.link_mode.unwrap_or_default(),
|
||||||
sources: SourceStrategy::from_args(value.no_sources.unwrap_or_default()),
|
sources: SourceStrategy::from_args(value.no_sources.unwrap_or_default()),
|
||||||
|
|
@ -2878,6 +2881,7 @@ impl From<ResolverInstallerOptions> for ResolverInstallerSettings {
|
||||||
link_mode: value.link_mode.unwrap_or_default(),
|
link_mode: value.link_mode.unwrap_or_default(),
|
||||||
no_build_isolation: value.no_build_isolation.unwrap_or_default(),
|
no_build_isolation: value.no_build_isolation.unwrap_or_default(),
|
||||||
no_build_isolation_package: value.no_build_isolation_package.unwrap_or_default(),
|
no_build_isolation_package: value.no_build_isolation_package.unwrap_or_default(),
|
||||||
|
extra_build_dependencies: value.extra_build_dependencies.unwrap_or_default(),
|
||||||
prerelease: value.prerelease.unwrap_or_default(),
|
prerelease: value.prerelease.unwrap_or_default(),
|
||||||
resolution: value.resolution.unwrap_or_default(),
|
resolution: value.resolution.unwrap_or_default(),
|
||||||
sources: SourceStrategy::from_args(value.no_sources.unwrap_or_default()),
|
sources: SourceStrategy::from_args(value.no_sources.unwrap_or_default()),
|
||||||
|
|
@ -2921,6 +2925,7 @@ pub(crate) struct PipSettings {
|
||||||
pub(crate) torch_backend: Option<TorchMode>,
|
pub(crate) torch_backend: Option<TorchMode>,
|
||||||
pub(crate) no_build_isolation: bool,
|
pub(crate) no_build_isolation: bool,
|
||||||
pub(crate) no_build_isolation_package: Vec<PackageName>,
|
pub(crate) no_build_isolation_package: Vec<PackageName>,
|
||||||
|
pub(crate) extra_build_dependencies: ExtraBuildDependencies,
|
||||||
pub(crate) build_options: BuildOptions,
|
pub(crate) build_options: BuildOptions,
|
||||||
pub(crate) allow_empty_requirements: bool,
|
pub(crate) allow_empty_requirements: bool,
|
||||||
pub(crate) strict: bool,
|
pub(crate) strict: bool,
|
||||||
|
|
@ -2988,6 +2993,7 @@ impl PipSettings {
|
||||||
only_binary,
|
only_binary,
|
||||||
no_build_isolation,
|
no_build_isolation,
|
||||||
no_build_isolation_package,
|
no_build_isolation_package,
|
||||||
|
extra_build_dependencies,
|
||||||
strict,
|
strict,
|
||||||
extra,
|
extra,
|
||||||
all_extras,
|
all_extras,
|
||||||
|
|
@ -3046,6 +3052,7 @@ impl PipSettings {
|
||||||
config_settings_package: top_level_config_settings_package,
|
config_settings_package: top_level_config_settings_package,
|
||||||
no_build_isolation: top_level_no_build_isolation,
|
no_build_isolation: top_level_no_build_isolation,
|
||||||
no_build_isolation_package: top_level_no_build_isolation_package,
|
no_build_isolation_package: top_level_no_build_isolation_package,
|
||||||
|
extra_build_dependencies: top_level_extra_build_dependencies,
|
||||||
exclude_newer: top_level_exclude_newer,
|
exclude_newer: top_level_exclude_newer,
|
||||||
link_mode: top_level_link_mode,
|
link_mode: top_level_link_mode,
|
||||||
compile_bytecode: top_level_compile_bytecode,
|
compile_bytecode: top_level_compile_bytecode,
|
||||||
|
|
@ -3082,6 +3089,8 @@ impl PipSettings {
|
||||||
let no_build_isolation = no_build_isolation.combine(top_level_no_build_isolation);
|
let no_build_isolation = no_build_isolation.combine(top_level_no_build_isolation);
|
||||||
let no_build_isolation_package =
|
let no_build_isolation_package =
|
||||||
no_build_isolation_package.combine(top_level_no_build_isolation_package);
|
no_build_isolation_package.combine(top_level_no_build_isolation_package);
|
||||||
|
let extra_build_dependencies =
|
||||||
|
extra_build_dependencies.combine(top_level_extra_build_dependencies);
|
||||||
let exclude_newer = exclude_newer.combine(top_level_exclude_newer);
|
let exclude_newer = exclude_newer.combine(top_level_exclude_newer);
|
||||||
let link_mode = link_mode.combine(top_level_link_mode);
|
let link_mode = link_mode.combine(top_level_link_mode);
|
||||||
let compile_bytecode = compile_bytecode.combine(top_level_compile_bytecode);
|
let compile_bytecode = compile_bytecode.combine(top_level_compile_bytecode);
|
||||||
|
|
@ -3177,6 +3186,10 @@ impl PipSettings {
|
||||||
.no_build_isolation_package
|
.no_build_isolation_package
|
||||||
.combine(no_build_isolation_package)
|
.combine(no_build_isolation_package)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
|
extra_build_dependencies: args
|
||||||
|
.extra_build_dependencies
|
||||||
|
.combine(extra_build_dependencies)
|
||||||
|
.unwrap_or_default(),
|
||||||
config_setting: args
|
config_setting: args
|
||||||
.config_settings
|
.config_settings
|
||||||
.combine(config_settings)
|
.combine(config_settings)
|
||||||
|
|
@ -3281,6 +3294,7 @@ impl<'a> From<&'a ResolverInstallerSettings> for InstallerSettingsRef<'a> {
|
||||||
config_settings_package: &settings.resolver.config_settings_package,
|
config_settings_package: &settings.resolver.config_settings_package,
|
||||||
no_build_isolation: settings.resolver.no_build_isolation,
|
no_build_isolation: settings.resolver.no_build_isolation,
|
||||||
no_build_isolation_package: &settings.resolver.no_build_isolation_package,
|
no_build_isolation_package: &settings.resolver.no_build_isolation_package,
|
||||||
|
extra_build_dependencies: &settings.resolver.extra_build_dependencies,
|
||||||
exclude_newer: settings.resolver.exclude_newer,
|
exclude_newer: settings.resolver.exclude_newer,
|
||||||
link_mode: settings.resolver.link_mode,
|
link_mode: settings.resolver.link_mode,
|
||||||
compile_bytecode: settings.compile_bytecode,
|
compile_bytecode: settings.compile_bytecode,
|
||||||
|
|
|
||||||
|
|
@ -3920,16 +3920,17 @@ fn config_settings_registry() {
|
||||||
.arg("iniconfig")
|
.arg("iniconfig")
|
||||||
.arg("--no-binary")
|
.arg("--no-binary")
|
||||||
.arg("iniconfig")
|
.arg("iniconfig")
|
||||||
.arg("-C=global-option=build_ext"), @r###"
|
.arg("-C=global-option=build_ext"), @r"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
Resolved 1 package in [TIME]
|
Resolved 1 package in [TIME]
|
||||||
|
Prepared 1 package in [TIME]
|
||||||
Installed 1 package in [TIME]
|
Installed 1 package in [TIME]
|
||||||
+ iniconfig==2.0.0
|
+ iniconfig==2.0.0
|
||||||
"###
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Uninstall the package.
|
// Uninstall the package.
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -373,6 +374,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -563,6 +565,7 @@ fn resolve_uv_toml() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -785,6 +788,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -942,6 +946,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -1143,6 +1148,7 @@ fn resolve_pyproject_toml() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -1392,6 +1398,7 @@ fn resolve_index_url() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -1651,6 +1658,7 @@ fn resolve_index_url() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -1865,6 +1873,7 @@ fn resolve_find_links() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -2044,6 +2053,7 @@ fn resolve_top_level() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -2283,6 +2293,7 @@ fn resolve_top_level() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -2505,6 +2516,7 @@ fn resolve_top_level() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -2683,6 +2695,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -2845,6 +2858,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -3007,6 +3021,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -3171,6 +3186,7 @@ fn resolve_user_configuration() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -3327,6 +3343,7 @@ fn resolve_tool() -> anyhow::Result<()> {
|
||||||
config_settings_package: None,
|
config_settings_package: None,
|
||||||
no_build_isolation: None,
|
no_build_isolation: None,
|
||||||
no_build_isolation_package: None,
|
no_build_isolation_package: None,
|
||||||
|
extra_build_dependencies: None,
|
||||||
exclude_newer: None,
|
exclude_newer: None,
|
||||||
link_mode: Some(
|
link_mode: Some(
|
||||||
Clone,
|
Clone,
|
||||||
|
|
@ -3369,6 +3386,7 @@ fn resolve_tool() -> anyhow::Result<()> {
|
||||||
link_mode: Clone,
|
link_mode: Clone,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
prerelease: IfNecessaryOrExplicit,
|
prerelease: IfNecessaryOrExplicit,
|
||||||
resolution: LowestDirect,
|
resolution: LowestDirect,
|
||||||
sources: Enabled,
|
sources: Enabled,
|
||||||
|
|
@ -3527,6 +3545,7 @@ fn resolve_poetry_toml() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -3757,6 +3776,7 @@ fn resolve_both() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -3991,6 +4011,7 @@ fn resolve_both_special_fields() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -4304,6 +4325,7 @@ fn resolve_config_file() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -4384,7 +4406,7 @@ fn resolve_config_file() -> anyhow::Result<()> {
|
||||||
|
|
|
|
||||||
1 | [project]
|
1 | [project]
|
||||||
| ^^^^^^^
|
| ^^^^^^^
|
||||||
unknown field `project`, expected one of `required-version`, `native-tls`, `offline`, `no-cache`, `cache-dir`, `preview`, `python-preference`, `python-downloads`, `concurrent-downloads`, `concurrent-builds`, `concurrent-installs`, `index`, `index-url`, `extra-index-url`, `no-index`, `find-links`, `index-strategy`, `keyring-provider`, `allow-insecure-host`, `resolution`, `prerelease`, `fork-strategy`, `dependency-metadata`, `config-settings`, `config-settings-package`, `no-build-isolation`, `no-build-isolation-package`, `exclude-newer`, `link-mode`, `compile-bytecode`, `no-sources`, `upgrade`, `upgrade-package`, `reinstall`, `reinstall-package`, `no-build`, `no-build-package`, `no-binary`, `no-binary-package`, `python-install-mirror`, `pypy-install-mirror`, `python-downloads-json-url`, `publish-url`, `trusted-publishing`, `check-url`, `add-bounds`, `pip`, `cache-keys`, `override-dependencies`, `constraint-dependencies`, `build-constraint-dependencies`, `environments`, `required-environments`, `conflicts`, `workspace`, `sources`, `managed`, `package`, `default-groups`, `dependency-groups`, `dev-dependencies`, `build-backend`
|
unknown field `project`, expected one of `required-version`, `native-tls`, `offline`, `no-cache`, `cache-dir`, `preview`, `python-preference`, `python-downloads`, `concurrent-downloads`, `concurrent-builds`, `concurrent-installs`, `index`, `index-url`, `extra-index-url`, `no-index`, `find-links`, `index-strategy`, `keyring-provider`, `allow-insecure-host`, `resolution`, `prerelease`, `fork-strategy`, `dependency-metadata`, `config-settings`, `config-settings-package`, `no-build-isolation`, `no-build-isolation-package`, `extra-build-dependencies`, `exclude-newer`, `link-mode`, `compile-bytecode`, `no-sources`, `upgrade`, `upgrade-package`, `reinstall`, `reinstall-package`, `no-build`, `no-build-package`, `no-binary`, `no-binary-package`, `python-install-mirror`, `pypy-install-mirror`, `python-downloads-json-url`, `publish-url`, `trusted-publishing`, `check-url`, `add-bounds`, `pip`, `cache-keys`, `override-dependencies`, `constraint-dependencies`, `build-constraint-dependencies`, `environments`, `required-environments`, `conflicts`, `workspace`, `sources`, `managed`, `package`, `default-groups`, `dependency-groups`, `dev-dependencies`, `build-backend`
|
||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -4559,6 +4581,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -4724,6 +4747,7 @@ fn resolve_skip_empty() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -4908,6 +4932,7 @@ fn allow_insecure_host() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -5153,6 +5178,7 @@ fn index_priority() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -5377,6 +5403,7 @@ fn index_priority() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -5607,6 +5634,7 @@ fn index_priority() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -5832,6 +5860,7 @@ fn index_priority() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -6064,6 +6093,7 @@ fn index_priority() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -6289,6 +6319,7 @@ fn index_priority() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -6458,6 +6489,7 @@ fn verify_hashes() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -6613,6 +6645,7 @@ fn verify_hashes() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -6766,6 +6799,7 @@ fn verify_hashes() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -6921,6 +6955,7 @@ fn verify_hashes() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -7074,6 +7109,7 @@ fn verify_hashes() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -7228,6 +7264,7 @@ fn verify_hashes() -> anyhow::Result<()> {
|
||||||
torch_backend: None,
|
torch_backend: None,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
build_options: BuildOptions {
|
build_options: BuildOptions {
|
||||||
no_binary: None,
|
no_binary: None,
|
||||||
no_build: None,
|
no_build: None,
|
||||||
|
|
@ -7320,7 +7357,7 @@ fn preview_features() {
|
||||||
show_settings: true,
|
show_settings: true,
|
||||||
preview: Preview {
|
preview: Preview {
|
||||||
flags: PreviewFeatures(
|
flags: PreviewFeatures(
|
||||||
PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS,
|
PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS | EXTRA_BUILD_DEPENDENCIES,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
python_preference: Managed,
|
python_preference: Managed,
|
||||||
|
|
@ -7386,6 +7423,7 @@ fn preview_features() {
|
||||||
link_mode: Clone,
|
link_mode: Clone,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
prerelease: IfNecessaryOrExplicit,
|
prerelease: IfNecessaryOrExplicit,
|
||||||
resolution: Highest,
|
resolution: Highest,
|
||||||
sources: Enabled,
|
sources: Enabled,
|
||||||
|
|
@ -7488,6 +7526,7 @@ fn preview_features() {
|
||||||
link_mode: Clone,
|
link_mode: Clone,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
prerelease: IfNecessaryOrExplicit,
|
prerelease: IfNecessaryOrExplicit,
|
||||||
resolution: Highest,
|
resolution: Highest,
|
||||||
sources: Enabled,
|
sources: Enabled,
|
||||||
|
|
@ -7524,7 +7563,7 @@ fn preview_features() {
|
||||||
show_settings: true,
|
show_settings: true,
|
||||||
preview: Preview {
|
preview: Preview {
|
||||||
flags: PreviewFeatures(
|
flags: PreviewFeatures(
|
||||||
PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS,
|
PYTHON_INSTALL_DEFAULT | PYTHON_UPGRADE | JSON_OUTPUT | PYLOCK | ADD_BOUNDS | EXTRA_BUILD_DEPENDENCIES,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
python_preference: Managed,
|
python_preference: Managed,
|
||||||
|
|
@ -7590,6 +7629,7 @@ fn preview_features() {
|
||||||
link_mode: Clone,
|
link_mode: Clone,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
prerelease: IfNecessaryOrExplicit,
|
prerelease: IfNecessaryOrExplicit,
|
||||||
resolution: Highest,
|
resolution: Highest,
|
||||||
sources: Enabled,
|
sources: Enabled,
|
||||||
|
|
@ -7692,6 +7732,7 @@ fn preview_features() {
|
||||||
link_mode: Clone,
|
link_mode: Clone,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
prerelease: IfNecessaryOrExplicit,
|
prerelease: IfNecessaryOrExplicit,
|
||||||
resolution: Highest,
|
resolution: Highest,
|
||||||
sources: Enabled,
|
sources: Enabled,
|
||||||
|
|
@ -7794,6 +7835,7 @@ fn preview_features() {
|
||||||
link_mode: Clone,
|
link_mode: Clone,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
prerelease: IfNecessaryOrExplicit,
|
prerelease: IfNecessaryOrExplicit,
|
||||||
resolution: Highest,
|
resolution: Highest,
|
||||||
sources: Enabled,
|
sources: Enabled,
|
||||||
|
|
@ -7898,6 +7940,7 @@ fn preview_features() {
|
||||||
link_mode: Clone,
|
link_mode: Clone,
|
||||||
no_build_isolation: false,
|
no_build_isolation: false,
|
||||||
no_build_isolation_package: [],
|
no_build_isolation_package: [],
|
||||||
|
extra_build_dependencies: {},
|
||||||
prerelease: IfNecessaryOrExplicit,
|
prerelease: IfNecessaryOrExplicit,
|
||||||
resolution: Highest,
|
resolution: Highest,
|
||||||
sources: Enabled,
|
sources: Enabled,
|
||||||
|
|
|
||||||
|
|
@ -1567,6 +1567,401 @@ fn sync_build_isolation_extra() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sync_extra_build_dependencies() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12").with_filtered_counts();
|
||||||
|
|
||||||
|
// Write a test package that arbitrarily requires `anyio` at build time
|
||||||
|
let child = context.temp_dir.child("child");
|
||||||
|
child.create_dir_all()?;
|
||||||
|
let child_pyproject_toml = child.child("pyproject.toml");
|
||||||
|
child_pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "child"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
backend-path = ["."]
|
||||||
|
build-backend = "build_backend"
|
||||||
|
"#})?;
|
||||||
|
let build_backend = child.child("build_backend.py");
|
||||||
|
build_backend.write_str(indoc! {r#"
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from hatchling.build import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
import anyio
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
print("Missing `anyio` module", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
"#})?;
|
||||||
|
child.child("src/child/__init__.py").touch()?;
|
||||||
|
|
||||||
|
let parent = &context.temp_dir;
|
||||||
|
let pyproject_toml = parent.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "parent"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
dependencies = ["child"]
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
child = { path = "child" }
|
||||||
|
"#})?;
|
||||||
|
|
||||||
|
context.venv().arg("--clear").assert().success();
|
||||||
|
// Running `uv sync` should fail due to missing build-dependencies
|
||||||
|
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
× Failed to build `child @ file://[TEMP_DIR]/child`
|
||||||
|
├─▶ The build backend returned an error
|
||||||
|
╰─▶ Call to `build_backend.build_wheel` failed (exit status: 1)
|
||||||
|
|
||||||
|
[stderr]
|
||||||
|
Missing `anyio` module
|
||||||
|
|
||||||
|
hint: This usually indicates a problem with the package or the build environment.
|
||||||
|
help: `child` was included because `parent` (v0.1.0) depends on `child`
|
||||||
|
");
|
||||||
|
|
||||||
|
// Adding `extra-build-dependencies` should solve the issue
|
||||||
|
pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "parent"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
dependencies = ["child"]
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
child = { path = "child" }
|
||||||
|
|
||||||
|
[tool.uv.extra-build-dependencies]
|
||||||
|
child = ["anyio"]
|
||||||
|
"#})?;
|
||||||
|
|
||||||
|
context.venv().arg("--clear").assert().success();
|
||||||
|
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning.
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
Prepared [N] packages in [TIME]
|
||||||
|
Installed [N] packages in [TIME]
|
||||||
|
+ child==0.1.0 (from file://[TEMP_DIR]/child)
|
||||||
|
");
|
||||||
|
|
||||||
|
// Adding `extra-build-dependencies` with the wrong name should fail the build
|
||||||
|
// (the cache is invalidated when extra build dependencies change)
|
||||||
|
pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "parent"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
dependencies = ["child"]
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
child = { path = "child" }
|
||||||
|
|
||||||
|
[tool.uv.extra-build-dependencies]
|
||||||
|
wrong_name = ["anyio"]
|
||||||
|
"#})?;
|
||||||
|
|
||||||
|
context.venv().arg("--clear").assert().success();
|
||||||
|
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning.
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
× Failed to build `child @ file://[TEMP_DIR]/child`
|
||||||
|
├─▶ The build backend returned an error
|
||||||
|
╰─▶ Call to `build_backend.build_wheel` failed (exit status: 1)
|
||||||
|
|
||||||
|
[stderr]
|
||||||
|
Missing `anyio` module
|
||||||
|
|
||||||
|
hint: This usually indicates a problem with the package or the build environment.
|
||||||
|
help: `child` was included because `parent` (v0.1.0) depends on `child`
|
||||||
|
");
|
||||||
|
|
||||||
|
// Write a test package that arbitrarily bans `anyio` at build time
|
||||||
|
let bad_child = context.temp_dir.child("bad_child");
|
||||||
|
bad_child.create_dir_all()?;
|
||||||
|
let bad_child_pyproject_toml = bad_child.child("pyproject.toml");
|
||||||
|
bad_child_pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "bad_child"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
backend-path = ["."]
|
||||||
|
build-backend = "build_backend"
|
||||||
|
"#})?;
|
||||||
|
let build_backend = bad_child.child("build_backend.py");
|
||||||
|
build_backend.write_str(indoc! {r#"
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from hatchling.build import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
import anyio
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
print("Found `anyio` module", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
"#})?;
|
||||||
|
bad_child.child("src/bad_child/__init__.py").touch()?;
|
||||||
|
|
||||||
|
// Depend on `bad_child` too
|
||||||
|
pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "parent"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
dependencies = ["child", "bad_child"]
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
child = { path = "child" }
|
||||||
|
bad_child = { path = "bad_child" }
|
||||||
|
|
||||||
|
[tool.uv.extra-build-dependencies]
|
||||||
|
child = ["anyio"]
|
||||||
|
bad_child = ["anyio"]
|
||||||
|
"#})?;
|
||||||
|
|
||||||
|
// Confirm that `bad_child` fails if anyio is provided
|
||||||
|
context.venv().arg("--clear").assert().success();
|
||||||
|
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning.
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
× Failed to build `bad-child @ file://[TEMP_DIR]/bad_child`
|
||||||
|
├─▶ The build backend returned an error
|
||||||
|
╰─▶ Call to `build_backend.build_wheel` failed (exit status: 1)
|
||||||
|
|
||||||
|
[stderr]
|
||||||
|
Found `anyio` module
|
||||||
|
|
||||||
|
hint: This usually indicates a problem with the package or the build environment.
|
||||||
|
help: `bad-child` was included because `parent` (v0.1.0) depends on `bad-child`
|
||||||
|
");
|
||||||
|
|
||||||
|
// But `anyio` is not provided to `bad_child` if scoped to `child`
|
||||||
|
pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "parent"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
dependencies = ["child", "bad_child"]
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
child = { path = "child" }
|
||||||
|
bad_child = { path = "bad_child" }
|
||||||
|
|
||||||
|
[tool.uv.extra-build-dependencies]
|
||||||
|
child = ["anyio"]
|
||||||
|
"#})?;
|
||||||
|
|
||||||
|
context.venv().arg("--clear").assert().success();
|
||||||
|
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning.
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
Prepared [N] packages in [TIME]
|
||||||
|
Installed [N] packages in [TIME]
|
||||||
|
+ bad-child==0.1.0 (from file://[TEMP_DIR]/bad_child)
|
||||||
|
+ child==0.1.0 (from file://[TEMP_DIR]/child)
|
||||||
|
");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sync_extra_build_dependencies_sources() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12").with_filtered_counts();
|
||||||
|
|
||||||
|
let anyio_local = context.workspace_root.join("scripts/packages/anyio_local");
|
||||||
|
|
||||||
|
// Write a test package that arbitrarily requires `anyio` at a specific _path_ at build time
|
||||||
|
let child = context.temp_dir.child("child");
|
||||||
|
child.create_dir_all()?;
|
||||||
|
let child_pyproject_toml = child.child("pyproject.toml");
|
||||||
|
child_pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "child"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
backend-path = ["."]
|
||||||
|
build-backend = "build_backend"
|
||||||
|
"#})?;
|
||||||
|
let build_backend = child.child("build_backend.py");
|
||||||
|
build_backend.write_str(&formatdoc! {r#"
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from hatchling.build import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
import anyio
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
print("Missing `anyio` module", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Check that we got the local version of anyio by checking for the marker
|
||||||
|
if not hasattr(anyio, 'LOCAL_ANYIO_MARKER'):
|
||||||
|
print("Found system anyio instead of local anyio", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
"#})?;
|
||||||
|
child.child("src/child/__init__.py").touch()?;
|
||||||
|
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(&formatdoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
dependencies = ["child"]
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
anyio = {{ path = "{anyio_local}" }}
|
||||||
|
child = {{ path = "child" }}
|
||||||
|
|
||||||
|
[tool.uv.extra-build-dependencies]
|
||||||
|
child = ["anyio"]
|
||||||
|
"#,
|
||||||
|
anyio_local = anyio_local.portable_display(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Running `uv sync` should succeed, as `anyio` is provided as a source
|
||||||
|
uv_snapshot!(context.filters(), context.sync(), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning.
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
Prepared [N] packages in [TIME]
|
||||||
|
Installed [N] packages in [TIME]
|
||||||
|
+ child==0.1.0 (from file://[TEMP_DIR]/child)
|
||||||
|
");
|
||||||
|
|
||||||
|
// TODO(zanieb): We want to test with `--no-sources` too but unfortunately that's not easy
|
||||||
|
// because it'll disable the `child` path source too!
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sync_extra_build_dependencies_sources_from_child() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12").with_filtered_counts();
|
||||||
|
|
||||||
|
let anyio_local = context.workspace_root.join("scripts/packages/anyio_local");
|
||||||
|
|
||||||
|
// Write a test package that arbitrarily requires `anyio` at a specific _path_ at build time
|
||||||
|
let child = context.temp_dir.child("child");
|
||||||
|
child.create_dir_all()?;
|
||||||
|
let child_pyproject_toml = child.child("pyproject.toml");
|
||||||
|
child_pyproject_toml.write_str(&formatdoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "child"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
backend-path = ["."]
|
||||||
|
build-backend = "build_backend"
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
anyio = {{ path = "{}" }}
|
||||||
|
"#, anyio_local.portable_display()
|
||||||
|
})?;
|
||||||
|
let build_backend = child.child("build_backend.py");
|
||||||
|
build_backend.write_str(&formatdoc! {r#"
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from hatchling.build import *
|
||||||
|
|
||||||
|
try:
|
||||||
|
import anyio
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
print("Missing `anyio` module", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Check that we got the local version of anyio by checking for the marker
|
||||||
|
if not hasattr(anyio, 'LOCAL_ANYIO_MARKER'):
|
||||||
|
print("Found system anyio instead of local anyio", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
"#})?;
|
||||||
|
child.child("src/child/__init__.py").touch()?;
|
||||||
|
|
||||||
|
let pyproject_toml = context.temp_dir.child("pyproject.toml");
|
||||||
|
pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "project"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
dependencies = ["child"]
|
||||||
|
|
||||||
|
[tool.uv.sources]
|
||||||
|
child = { path = "child" }
|
||||||
|
|
||||||
|
[tool.uv.extra-build-dependencies]
|
||||||
|
child = ["anyio"]
|
||||||
|
"#,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
// Running `uv sync` should fail due to the unapplied source
|
||||||
|
uv_snapshot!(context.filters(), context.sync().arg("--reinstall").arg("--refresh"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: The `extra-build-dependencies` option is experimental and may change without warning. Pass `--preview-features extra-build-dependencies` to disable this warning.
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
× Failed to build `child @ file://[TEMP_DIR]/child`
|
||||||
|
├─▶ The build backend returned an error
|
||||||
|
╰─▶ Call to `build_backend.build_wheel` failed (exit status: 1)
|
||||||
|
|
||||||
|
[stderr]
|
||||||
|
Found system anyio instead of local anyio
|
||||||
|
|
||||||
|
hint: This usually indicates a problem with the package or the build environment.
|
||||||
|
help: `child` was included because `project` (v0.1.0) depends on `child`
|
||||||
|
");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Avoid using incompatible versions for build dependencies that are also part of the resolved
|
/// Avoid using incompatible versions for build dependencies that are also part of the resolved
|
||||||
/// environment. This is a very subtle issue, but: when locking, we don't enforce platform
|
/// environment. This is a very subtle issue, but: when locking, we don't enforce platform
|
||||||
/// compatibility. So, if we reuse the resolver state to install, and the install itself has to
|
/// compatibility. So, if we reuse the resolver state to install, and the install itself has to
|
||||||
|
|
@ -4198,6 +4593,187 @@ fn no_install_project_no_build() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sync_extra_build_dependencies_script() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12").with_filtered_counts();
|
||||||
|
|
||||||
|
// Write a test package that arbitrarily requires `anyio` at build time
|
||||||
|
let child = context.temp_dir.child("child");
|
||||||
|
child.create_dir_all()?;
|
||||||
|
let child_pyproject_toml = child.child("pyproject.toml");
|
||||||
|
child_pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "child"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
backend-path = ["."]
|
||||||
|
build-backend = "build_backend"
|
||||||
|
"#})?;
|
||||||
|
let build_backend = child.child("build_backend.py");
|
||||||
|
build_backend.write_str(indoc! {r#"
|
||||||
|
import sys
|
||||||
|
from hatchling.build import *
|
||||||
|
try:
|
||||||
|
import anyio
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
print("Missing `anyio` module", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
"#})?;
|
||||||
|
child.child("src/child/__init__.py").touch()?;
|
||||||
|
|
||||||
|
// Create a script that depends on the child package
|
||||||
|
let script = context.temp_dir.child("script.py");
|
||||||
|
script.write_str(indoc! {r#"
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.12"
|
||||||
|
# dependencies = ["child"]
|
||||||
|
#
|
||||||
|
# [tool.uv.sources]
|
||||||
|
# child = { path = "child" }
|
||||||
|
# ///
|
||||||
|
"#})?;
|
||||||
|
|
||||||
|
let filters = context
|
||||||
|
.filters()
|
||||||
|
.into_iter()
|
||||||
|
.chain(vec![(
|
||||||
|
r"environments-v2/script-[a-z0-9]+",
|
||||||
|
"environments-v2/script-[HASH]",
|
||||||
|
)])
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Running `uv sync` should fail due to missing build-dependencies
|
||||||
|
uv_snapshot!(filters, context.sync().arg("--script").arg("script.py"), @r"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Creating script environment at: [CACHE_DIR]/environments-v2/script-[HASH]
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
× Failed to build `child @ file://[TEMP_DIR]/child`
|
||||||
|
├─▶ The build backend returned an error
|
||||||
|
╰─▶ Call to `build_backend.build_wheel` failed (exit status: 1)
|
||||||
|
|
||||||
|
[stderr]
|
||||||
|
Missing `anyio` module
|
||||||
|
|
||||||
|
hint: This usually indicates a problem with the package or the build environment.
|
||||||
|
");
|
||||||
|
|
||||||
|
// Add extra build dependencies to the script
|
||||||
|
script.write_str(indoc! {r#"
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.12"
|
||||||
|
# dependencies = ["child"]
|
||||||
|
#
|
||||||
|
# [tool.uv.sources]
|
||||||
|
# child = { path = "child" }
|
||||||
|
#
|
||||||
|
# [tool.uv.extra-build-dependencies]
|
||||||
|
# child = ["anyio"]
|
||||||
|
# ///
|
||||||
|
"#})?;
|
||||||
|
|
||||||
|
// Running `uv sync` should now succeed due to extra build-dependencies
|
||||||
|
context.venv().arg("--clear").assert().success();
|
||||||
|
uv_snapshot!(filters, context.sync().arg("--script").arg("script.py"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Using script environment at: [CACHE_DIR]/environments-v2/script-[HASH]
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
Prepared [N] packages in [TIME]
|
||||||
|
Installed [N] packages in [TIME]
|
||||||
|
+ child==0.1.0 (from file://[TEMP_DIR]/child)
|
||||||
|
");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sync_extra_build_dependencies_script_sources() -> Result<()> {
|
||||||
|
let context = TestContext::new("3.12").with_filtered_counts();
|
||||||
|
let anyio_local = context.workspace_root.join("scripts/packages/anyio_local");
|
||||||
|
|
||||||
|
// Write a test package that arbitrarily requires `anyio` at a specific _path_ at build time
|
||||||
|
let child = context.temp_dir.child("child");
|
||||||
|
child.create_dir_all()?;
|
||||||
|
let child_pyproject_toml = child.child("pyproject.toml");
|
||||||
|
child_pyproject_toml.write_str(indoc! {r#"
|
||||||
|
[project]
|
||||||
|
name = "child"
|
||||||
|
version = "0.1.0"
|
||||||
|
requires-python = ">=3.9"
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling"]
|
||||||
|
backend-path = ["."]
|
||||||
|
build-backend = "build_backend"
|
||||||
|
"#})?;
|
||||||
|
let build_backend = child.child("build_backend.py");
|
||||||
|
build_backend.write_str(&formatdoc! {r#"
|
||||||
|
import sys
|
||||||
|
from hatchling.build import *
|
||||||
|
try:
|
||||||
|
import anyio
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
print("Missing `anyio` module", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Check that we got the local version of anyio by checking for the marker
|
||||||
|
if not hasattr(anyio, 'LOCAL_ANYIO_MARKER'):
|
||||||
|
print("Found system anyio instead of local anyio", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
"#})?;
|
||||||
|
child.child("src/child/__init__.py").touch()?;
|
||||||
|
|
||||||
|
// Create a script that depends on the child package
|
||||||
|
let script = context.temp_dir.child("script.py");
|
||||||
|
script.write_str(&formatdoc! {r#"
|
||||||
|
# /// script
|
||||||
|
# requires-python = ">=3.12"
|
||||||
|
# dependencies = ["child"]
|
||||||
|
#
|
||||||
|
# [tool.uv.sources]
|
||||||
|
# anyio = {{ path = "{}" }}
|
||||||
|
# child = {{ path = "child" }}
|
||||||
|
#
|
||||||
|
# [tool.uv.extra-build-dependencies]
|
||||||
|
# child = ["anyio"]
|
||||||
|
# ///
|
||||||
|
"#, anyio_local.portable_display()
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let filters = context
|
||||||
|
.filters()
|
||||||
|
.into_iter()
|
||||||
|
.chain(vec![(
|
||||||
|
r"environments-v2/script-[a-z0-9]+",
|
||||||
|
"environments-v2/script-[HASH]",
|
||||||
|
)])
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// Running `uv sync` should succeed with the sources applied
|
||||||
|
uv_snapshot!(filters, context.sync().arg("--script").arg("script.py"), @r"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
Creating script environment at: [CACHE_DIR]/environments-v2/script-[HASH]
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
Prepared [N] packages in [TIME]
|
||||||
|
Installed [N] packages in [TIME]
|
||||||
|
+ child==0.1.0 (from file://[TEMP_DIR]/child)
|
||||||
|
");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn virtual_no_build() -> Result<()> {
|
fn virtual_no_build() -> Result<()> {
|
||||||
let context = TestContext::new("3.12");
|
let context = TestContext::new("3.12");
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,28 @@ environments = ["sys_platform == 'darwin'"]
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### [`extra-build-dependencies`](#extra-build-dependencies) {: #extra-build-dependencies }
|
||||||
|
|
||||||
|
Additional build dependencies for packages.
|
||||||
|
|
||||||
|
This allows extending the PEP 517 build environment for the project's dependencies with
|
||||||
|
additional packages. This is useful for packages that assume the presence of packages, like,
|
||||||
|
`pip`, and do not declare them as build dependencies.
|
||||||
|
|
||||||
|
**Default value**: `[]`
|
||||||
|
|
||||||
|
**Type**: `dict`
|
||||||
|
|
||||||
|
**Example usage**:
|
||||||
|
|
||||||
|
```toml title="pyproject.toml"
|
||||||
|
|
||||||
|
[tool.uv.extra-build-dependencies]
|
||||||
|
pytest = ["pip"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### [`index`](#index) {: #index }
|
### [`index`](#index) {: #index }
|
||||||
|
|
||||||
The indexes to use when resolving dependencies.
|
The indexes to use when resolving dependencies.
|
||||||
|
|
@ -1135,6 +1157,36 @@ behave consistently across timezones.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### [`extra-build-dependencies`](#extra-build-dependencies) {: #extra-build-dependencies }
|
||||||
|
|
||||||
|
Additional build dependencies for packages.
|
||||||
|
|
||||||
|
This allows extending the PEP 517 build environment for the project's dependencies with
|
||||||
|
additional packages. This is useful for packages that assume the presence of packages, like,
|
||||||
|
`pip`, and do not declare them as build dependencies.
|
||||||
|
|
||||||
|
**Default value**: `[]`
|
||||||
|
|
||||||
|
**Type**: `dict`
|
||||||
|
|
||||||
|
**Example usage**:
|
||||||
|
|
||||||
|
=== "pyproject.toml"
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.uv]
|
||||||
|
[extra-build-dependencies]
|
||||||
|
pytest = ["setuptools"]
|
||||||
|
```
|
||||||
|
=== "uv.toml"
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[extra-build-dependencies]
|
||||||
|
pytest = ["setuptools"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### [`extra-index-url`](#extra-index-url) {: #extra-index-url }
|
### [`extra-index-url`](#extra-index-url) {: #extra-index-url }
|
||||||
|
|
||||||
Extra URLs of package indexes to use, in addition to `--index-url`.
|
Extra URLs of package indexes to use, in addition to `--index-url`.
|
||||||
|
|
@ -2596,6 +2648,38 @@ Only applies to `pyproject.toml`, `setup.py`, and `setup.cfg` sources.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
#### [`extra-build-dependencies`](#pip_extra-build-dependencies) {: #pip_extra-build-dependencies }
|
||||||
|
<span id="extra-build-dependencies"></span>
|
||||||
|
|
||||||
|
Additional build dependencies for packages.
|
||||||
|
|
||||||
|
This allows extending the PEP 517 build environment for the project's dependencies with
|
||||||
|
additional packages. This is useful for packages that assume the presence of packages, like,
|
||||||
|
`pip`, and do not declare them as build dependencies.
|
||||||
|
|
||||||
|
**Default value**: `[]`
|
||||||
|
|
||||||
|
**Type**: `dict`
|
||||||
|
|
||||||
|
**Example usage**:
|
||||||
|
|
||||||
|
=== "pyproject.toml"
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.uv.pip]
|
||||||
|
[extra-build-dependencies]
|
||||||
|
pytest = ["setuptools"]
|
||||||
|
```
|
||||||
|
=== "uv.toml"
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[pip]
|
||||||
|
[extra-build-dependencies]
|
||||||
|
pytest = ["setuptools"]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
#### [`extra-index-url`](#pip_extra-index-url) {: #pip_extra-index-url }
|
#### [`extra-index-url`](#pip_extra-index-url) {: #pip_extra-index-url }
|
||||||
<span id="extra-index-url"></span>
|
<span id="extra-index-url"></span>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
# This is a local dummy anyio package
|
||||||
|
LOCAL_ANYIO_MARKER = True
|
||||||
|
|
@ -225,6 +225,17 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"extra-build-dependencies": {
|
||||||
|
"description": "Additional build dependencies for packages.\n\nThis allows extending the PEP 517 build environment for the project's dependencies with\nadditional packages. This is useful for packages that assume the presence of packages, like,\n`pip`, and do not declare them as build dependencies.",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/ToolUvExtraBuildDependencies"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"extra-index-url": {
|
"extra-index-url": {
|
||||||
"description": "Extra URLs of package indexes to use, in addition to `--index-url`.\n\nAccepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)\n(the simple repository API), or a local directory laid out in the same format.\n\nAll indexes provided via this flag take priority over the index specified by\n[`index_url`](#index-url) or [`index`](#index) with `default = true`. When multiple indexes\nare provided, earlier values take priority.\n\nTo control uv's resolution strategy when multiple indexes are present, see\n[`index_strategy`](#index-strategy).\n\n(Deprecated: use `index` instead.)",
|
"description": "Extra URLs of package indexes to use, in addition to `--index-url`.\n\nAccepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)\n(the simple repository API), or a local directory laid out in the same format.\n\nAll indexes provided via this flag take priority over the index specified by\n[`index_url`](#index-url) or [`index`](#index) with `default = true`. When multiple indexes\nare provided, earlier values take priority.\n\nTo control uv's resolution strategy when multiple indexes are present, see\n[`index_strategy`](#index-strategy).\n\n(Deprecated: use `index` instead.)",
|
||||||
"type": [
|
"type": [
|
||||||
|
|
@ -1312,6 +1323,19 @@
|
||||||
"$ref": "#/definitions/ExtraName"
|
"$ref": "#/definitions/ExtraName"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"extra-build-dependencies": {
|
||||||
|
"description": "Additional build dependencies for packages.\n\nThis allows extending the PEP 517 build environment for the project's dependencies with\nadditional packages. This is useful for packages that assume the presence of packages, like,\n`pip`, and do not declare them as build dependencies.",
|
||||||
|
"type": [
|
||||||
|
"object",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/Requirement"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"extra-index-url": {
|
"extra-index-url": {
|
||||||
"description": "Extra URLs of package indexes to use, in addition to `--index-url`.\n\nAccepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)\n(the simple repository API), or a local directory laid out in the same format.\n\nAll indexes provided via this flag take priority over the index specified by\n[`index_url`](#index-url). When multiple indexes are provided, earlier values take priority.\n\nTo control uv's resolution strategy when multiple indexes are present, see\n[`index_strategy`](#index-strategy).",
|
"description": "Extra URLs of package indexes to use, in addition to `--index-url`.\n\nAccepts either a repository compliant with [PEP 503](https://peps.python.org/pep-0503/)\n(the simple repository API), or a local directory laid out in the same format.\n\nAll indexes provided via this flag take priority over the index specified by\n[`index_url`](#index-url). When multiple indexes are provided, earlier values take priority.\n\nTo control uv's resolution strategy when multiple indexes are present, see\n[`index_strategy`](#index-strategy).",
|
||||||
"type": [
|
"type": [
|
||||||
|
|
@ -2341,6 +2365,15 @@
|
||||||
"$ref": "#/definitions/DependencyGroupSettings"
|
"$ref": "#/definitions/DependencyGroupSettings"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ToolUvExtraBuildDependencies": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/Requirement"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ToolUvSources": {
|
"ToolUvSources": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue