Skip to content

Commit

Permalink
Shrink PythonEnvironment API
Browse files Browse the repository at this point in the history
# Conflicts:
#	crates/uv-toolchain/src/environment.rs
  • Loading branch information
zanieb committed Jun 7, 2024
1 parent 3bc6945 commit b4f2aaa
Show file tree
Hide file tree
Showing 19 changed files with 353 additions and 407 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/bench/benches/uv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn resolve_warm_jupyter(c: &mut Criterion<WallTime>) {
.unwrap();

let cache = &Cache::from_path("../../.cache").init().unwrap();
let venv = PythonEnvironment::from_virtualenv(cache).unwrap();
let venv = PythonEnvironment::from_root("../../.venv", cache).unwrap();
let client = &RegistryClientBuilder::new(cache.clone()).build();
let manifest = &Manifest::simple(vec![Requirement::from(
pep508_rs::Requirement::from_str("jupyter").unwrap(),
Expand Down Expand Up @@ -44,7 +44,7 @@ fn resolve_warm_airflow(c: &mut Criterion<WallTime>) {
.unwrap();

let cache = &Cache::from_path("../../.cache").init().unwrap();
let venv = PythonEnvironment::from_virtualenv(cache).unwrap();
let venv = PythonEnvironment::from_root("../../.venv", cache).unwrap();
let client = &RegistryClientBuilder::new(cache.clone()).build();
let manifest = &Manifest::simple(vec![
Requirement::from(pep508_rs::Requirement::from_str("apache-airflow[all]").unwrap()),
Expand Down
6 changes: 3 additions & 3 deletions crates/uv-dev/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use uv_configuration::{
use uv_dispatch::BuildDispatch;
use uv_git::GitResolver;
use uv_resolver::{FlatIndex, InMemoryIndex};
use uv_toolchain::PythonEnvironment;
use uv_toolchain::Toolchain;
use uv_types::{BuildContext, BuildIsolation, InFlight};

#[derive(Parser)]
Expand Down Expand Up @@ -65,12 +65,12 @@ pub(crate) async fn build(args: BuildArgs) -> Result<PathBuf> {
let index = InMemoryIndex::default();
let index_urls = IndexLocations::default();
let setup_py = SetupPyStrategy::default();
let venv = PythonEnvironment::from_virtualenv(&cache)?;
let toolchain = Toolchain::find_virtualenv(&cache)?;

let build_dispatch = BuildDispatch::new(
&client,
&cache,
venv.interpreter(),
toolchain.interpreter(),
&index_urls,
&flat_index,
&index,
Expand Down
6 changes: 3 additions & 3 deletions crates/uv-dev/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::PathBuf;
use clap::Parser;
use tracing::info;
use uv_cache::{Cache, CacheArgs};
use uv_toolchain::PythonEnvironment;
use uv_toolchain::Toolchain;

#[derive(Parser)]
pub(crate) struct CompileArgs {
Expand All @@ -20,8 +20,8 @@ pub(crate) async fn compile(args: CompileArgs) -> anyhow::Result<()> {
let interpreter = if let Some(python) = args.python {
python
} else {
let venv = PythonEnvironment::from_virtualenv(&cache)?;
venv.python_executable().to_path_buf()
let interpreter = Toolchain::find_virtualenv(&cache)?.into_interpreter();
interpreter.sys_executable().to_path_buf()
};

let files = uv_installer::compile_tree(
Expand Down
1 change: 0 additions & 1 deletion crates/uv-resolver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,5 @@ tracing = { workspace = true }
url = { workspace = true }

[dev-dependencies]
once_cell = { version = "1.19.0" }
insta = { version = "1.36.1" }
toml = { workspace = true }
108 changes: 8 additions & 100 deletions crates/uv-toolchain/src/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;

use uv_cache::Cache;
use uv_configuration::PreviewMode;
use uv_fs::{LockedFile, Simplified};

use crate::discovery::{SystemPython, ToolchainRequest, ToolchainSources};
use crate::toolchain::Toolchain;
use crate::virtualenv::{virtualenv_python_executable, PyVenvConfiguration};
use crate::{
find_default_toolchain, find_toolchain, Error, Interpreter, Prefix, Target, ToolchainSource,
};
use crate::{Error, Interpreter, Prefix, Target};

/// A Python environment, consisting of a Python [`Interpreter`] and its associated paths.
#[derive(Debug, Clone)]
Expand All @@ -24,82 +21,13 @@ struct PythonEnvironmentShared {
}

impl PythonEnvironment {
/// Find a [`PythonEnvironment`].
///
/// This is the standard interface for discovering a Python environment for use with uv.
pub fn find(
python: Option<&str>,
system: SystemPython,
preview: PreviewMode,
cache: &Cache,
) -> Result<Self, Error> {
if let Some(python) = python {
Self::from_requested_python(python, system, preview, cache)
} else if system.is_preferred() {
Self::from_default_python(preview, cache)
} else {
// First check for a parent intepreter
// We gate this check to avoid an extra log message when it is not set
if std::env::var_os("UV_INTERNAL__PARENT_INTERPRETER").is_some() {
match Self::from_parent_interpreter(system, cache) {
Ok(env) => return Ok(env),
Err(Error::NotFound(_)) => {}
Err(err) => return Err(err),
}
}

// Then a virtual environment
match Self::from_virtualenv(cache) {
Ok(venv) => Ok(venv),
Err(Error::NotFound(_)) if system.is_allowed() => {
Self::from_default_python(preview, cache)
}
Err(err) => Err(err),
}
}
}

/// Create a [`PythonEnvironment`] for an existing virtual environment.
///
/// Allows Conda environments (via `CONDA_PREFIX`) though they are not technically virtual environments.
pub fn from_virtualenv(cache: &Cache) -> Result<Self, Error> {
let sources = ToolchainSources::VirtualEnv;
let request = ToolchainRequest::Any;
let toolchain = find_toolchain(&request, SystemPython::Disallowed, &sources, cache)??;

debug_assert!(
toolchain.interpreter().is_virtualenv()
|| matches!(toolchain.source(), ToolchainSource::CondaPrefix),
"Not a virtualenv (source: {}, prefix: {})",
toolchain.source(),
toolchain.interpreter().sys_base_prefix().display()
);

Ok(Self(Arc::new(PythonEnvironmentShared {
root: toolchain.interpreter().sys_prefix().to_path_buf(),
interpreter: toolchain.into_interpreter(),
})))
}

/// Create a [`PythonEnvironment`] for the parent interpreter i.e. the executable in `python -m uv ...`
pub fn from_parent_interpreter(system: SystemPython, cache: &Cache) -> Result<Self, Error> {
let sources = ToolchainSources::from_sources([ToolchainSource::ParentInterpreter]);
let request = ToolchainRequest::Any;
let toolchain = find_toolchain(&request, system, &sources, cache)??;

Ok(Self(Arc::new(PythonEnvironmentShared {
root: toolchain.interpreter().sys_prefix().to_path_buf(),
interpreter: toolchain.into_interpreter(),
})))
}

/// Create a [`PythonEnvironment`] from the virtual environment at the given root.
pub fn from_root(root: &Path, cache: &Cache) -> Result<Self, Error> {
let venv = match fs_err::canonicalize(root) {
pub fn from_root(root: impl AsRef<Path>, cache: &Cache) -> Result<Self, Error> {
let venv = match fs_err::canonicalize(root.as_ref()) {
Ok(venv) => venv,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
return Err(Error::NotFound(
crate::ToolchainNotFound::DirectoryNotFound(root.to_path_buf()),
crate::ToolchainNotFound::DirectoryNotFound(root.as_ref().to_path_buf()),
));
}
Err(err) => return Err(Error::Discovery(err.into())),
Expand All @@ -113,29 +41,9 @@ impl PythonEnvironment {
})))
}

/// Create a [`PythonEnvironment`] for a Python interpreter specifier (e.g., a path or a binary name).
pub fn from_requested_python(
request: &str,
system: SystemPython,
preview: PreviewMode,
cache: &Cache,
) -> Result<Self, Error> {
let sources = ToolchainSources::from_settings(system, preview);
let request = ToolchainRequest::parse(request);
let interpreter = find_toolchain(&request, system, &sources, cache)??.into_interpreter();
Ok(Self(Arc::new(PythonEnvironmentShared {
root: interpreter.sys_prefix().to_path_buf(),
interpreter,
})))
}

/// Create a [`PythonEnvironment`] for the default Python interpreter.
pub fn from_default_python(preview: PreviewMode, cache: &Cache) -> Result<Self, Error> {
let interpreter = find_default_toolchain(preview, cache)??.into_interpreter();
Ok(Self(Arc::new(PythonEnvironmentShared {
root: interpreter.sys_prefix().to_path_buf(),
interpreter,
})))
/// Create a [`PythonEnvironment`] from an existing [`Toolchain`].
pub fn from_toolchain(toolchain: Toolchain) -> Self {
Self::from_interpreter(toolchain.into_interpreter())
}

/// Create a [`PythonEnvironment`] from an existing [`Interpreter`].
Expand Down
Loading

0 comments on commit b4f2aaa

Please sign in to comment.