mirror of https://github.com/astral-sh/uv
Make the `BuildDispatch` interpreter method async (#14956)
This is a bit of a weird request, but in [pixi](https://pixi.sh) we are making use of this function to lazily instantiate a conda environment. Well, in actuality we are using a shim to the `BuildDispatch` to actually to only create a conda prefix, if some package needs to be built during the resolution phase. Otherwise we can resolve everything without an enviroment containing a python intepreter. We are using a method now - that uses the runtime to run async code inside this function, as `interpreter` is the first method called on a `BuildContext` when running a source build - using `tokio::Handle::block_on`. However was causing a deadlock in very specific situations, me and @baszalmstra + @wolfv have investigated this thoroughly, but have not been able to find the root cause. It would hang in a part of the uv code that hits the index, but that is **after** all of our initialization *and the blocking call* was completed. Changing this to be fully async fixes the problem, this requires this method to be async though. We get that this is not necessarily required, and we might find a workaround, but I wanted to try it this way first. Thanks!
This commit is contained in:
parent
3df972f18a
commit
fc0f637406
|
|
@ -175,7 +175,7 @@ impl<'a> BuildDispatch<'a> {
|
||||||
impl BuildContext for BuildDispatch<'_> {
|
impl BuildContext for BuildDispatch<'_> {
|
||||||
type SourceDistBuilder = SourceBuild;
|
type SourceDistBuilder = SourceBuild;
|
||||||
|
|
||||||
fn interpreter(&self) -> &Interpreter {
|
async fn interpreter(&self) -> &Interpreter {
|
||||||
self.interpreter
|
self.interpreter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2386,11 +2386,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
let base_python = if cfg!(unix) {
|
let base_python = if cfg!(unix) {
|
||||||
self.build_context
|
self.build_context
|
||||||
.interpreter()
|
.interpreter()
|
||||||
|
.await
|
||||||
.find_base_python()
|
.find_base_python()
|
||||||
.map_err(Error::BaseInterpreter)?
|
.map_err(Error::BaseInterpreter)?
|
||||||
} else {
|
} else {
|
||||||
self.build_context
|
self.build_context
|
||||||
.interpreter()
|
.interpreter()
|
||||||
|
.await
|
||||||
.to_base_python()
|
.to_base_python()
|
||||||
.map_err(Error::BaseInterpreter)?
|
.map_err(Error::BaseInterpreter)?
|
||||||
};
|
};
|
||||||
|
|
@ -2485,7 +2487,7 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
// Ensure that the _installed_ Python version is compatible with the `requires-python`
|
// Ensure that the _installed_ Python version is compatible with the `requires-python`
|
||||||
// specifier.
|
// specifier.
|
||||||
if let Some(requires_python) = source.requires_python() {
|
if let Some(requires_python) = source.requires_python() {
|
||||||
let installed = self.build_context.interpreter().python_version();
|
let installed = self.build_context.interpreter().await.python_version();
|
||||||
let target = release_specifiers_to_ranges(requires_python.clone())
|
let target = release_specifiers_to_ranges(requires_python.clone())
|
||||||
.bounding_range()
|
.bounding_range()
|
||||||
.map(|bounding_range| bounding_range.0.cloned())
|
.map(|bounding_range| bounding_range.0.cloned())
|
||||||
|
|
@ -2507,11 +2509,13 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> {
|
||||||
let base_python = if cfg!(unix) {
|
let base_python = if cfg!(unix) {
|
||||||
self.build_context
|
self.build_context
|
||||||
.interpreter()
|
.interpreter()
|
||||||
|
.await
|
||||||
.find_base_python()
|
.find_base_python()
|
||||||
.map_err(Error::BaseInterpreter)?
|
.map_err(Error::BaseInterpreter)?
|
||||||
} else {
|
} else {
|
||||||
self.build_context
|
self.build_context
|
||||||
.interpreter()
|
.interpreter()
|
||||||
|
.await
|
||||||
.to_base_python()
|
.to_base_python()
|
||||||
.map_err(Error::BaseInterpreter)?
|
.map_err(Error::BaseInterpreter)?
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,10 @@ use crate::BuildArena;
|
||||||
pub trait BuildContext {
|
pub trait BuildContext {
|
||||||
type SourceDistBuilder: SourceBuildTrait;
|
type SourceDistBuilder: SourceBuildTrait;
|
||||||
|
|
||||||
|
// Note: this function is async deliberately, because downstream code may need to
|
||||||
|
// run async code to get the interpreter, to resolve the Python version.
|
||||||
/// Return a reference to the interpreter.
|
/// Return a reference to the interpreter.
|
||||||
fn interpreter(&self) -> &Interpreter;
|
fn interpreter(&self) -> impl Future<Output = &Interpreter> + '_;
|
||||||
|
|
||||||
/// Return a reference to the cache.
|
/// Return a reference to the cache.
|
||||||
fn cache(&self) -> &Cache;
|
fn cache(&self) -> &Cache;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue