Skip to content

Commit

Permalink
Add arg
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Feb 27, 2024
1 parent 32e5cac commit 4a086a3
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 70 deletions.
2 changes: 1 addition & 1 deletion crates/uv-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ async fn run_python_script(
) -> Result<Output, Error> {
// Prepend the venv bin dir to PATH
let new_path = if let Some(old_path) = env::var_os("PATH") {
let new_path = iter::once(venv.bin_dir()).chain(env::split_paths(&old_path));
let new_path = iter::once(venv.bin_dir().to_path_buf()).chain(env::split_paths(&old_path));
env::join_paths(new_path).map_err(Error::BuildScriptPath)?
} else {
OsString::from("")
Expand Down
2 changes: 1 addition & 1 deletion crates/uv-interpreter/src/get_interpreter_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def format_full_version(info):
"markers": markers,
"base_prefix": sys.base_prefix,
"base_exec_prefix": sys.base_exec_prefix,
"stdlib": sysconfig.get_path("stdlib"),
"sys_executable": sys.executable,
"sysconfig": sysconfig.get_paths(),
}
print(json.dumps(interpreter_info))
100 changes: 78 additions & 22 deletions crates/uv-interpreter/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ use crate::{find_requested_python, Error, PythonVersion};
/// A Python executable and its associated platform markers.
#[derive(Debug, Clone)]
pub struct Interpreter {
pub(crate) platform: PythonPlatform,
pub(crate) platform: Platform,
pub(crate) markers: Box<MarkerEnvironment>,
pub(crate) sysconfig: Sysconfig,
pub(crate) base_exec_prefix: PathBuf,
pub(crate) base_prefix: PathBuf,
pub(crate) stdlib: PathBuf,
pub(crate) sys_executable: PathBuf,
tags: OnceCell<Tags>,
}
Expand All @@ -49,32 +49,34 @@ impl Interpreter {
);

Ok(Self {
platform: PythonPlatform(platform.to_owned()),
platform: platform.to_owned(),
markers: Box::new(info.markers),
sysconfig: info.sysconfig,
base_exec_prefix: info.base_exec_prefix,
base_prefix: info.base_prefix,
stdlib: info.stdlib,
sys_executable: info.sys_executable,
tags: OnceCell::new(),
})
}

// TODO(konstin): Find a better way mocking the fields
pub fn artificial(
platform: Platform,
markers: MarkerEnvironment,
base_exec_prefix: PathBuf,
base_prefix: PathBuf,
sys_executable: PathBuf,
stdlib: PathBuf,
) -> Self {
pub fn artificial(platform: Platform, markers: MarkerEnvironment) -> Self {
Self {
platform: PythonPlatform(platform),
platform,
markers: Box::new(markers),
base_exec_prefix,
base_prefix,
stdlib,
sys_executable,
sysconfig: Sysconfig {
stdlib: PathBuf::from("/dev/null"),
platstdlib: PathBuf::from("/dev/null"),
purelib: PathBuf::from("/dev/null"),
platlib: PathBuf::from("/dev/null"),
include: PathBuf::from("/dev/null"),
platinclude: PathBuf::from("/dev/null"),
scripts: PathBuf::from("/dev/null"),
data: PathBuf::from("/dev/null"),
},
base_exec_prefix: PathBuf::from("/dev/null"),
base_prefix: PathBuf::from("/dev/null"),
sys_executable: PathBuf::from("/dev/null"),
tags: OnceCell::new(),
}
}
Expand Down Expand Up @@ -287,28 +289,82 @@ impl Interpreter {
pub fn implementation_name(&self) -> &str {
&self.markers.implementation_name
}

pub fn base_exec_prefix(&self) -> &Path {
&self.base_exec_prefix
}

pub fn base_prefix(&self) -> &Path {
&self.base_prefix
}

/// `sysconfig.get_path("stdlib")`
pub fn stdlib(&self) -> &Path {
&self.stdlib
}
/// Return the `sys.executable` path for this Python interpreter.
pub fn sys_executable(&self) -> &Path {
&self.sys_executable
}

/// Return the `stdlib` path for this Python interpreter, as returned by `sysconfig.get_paths()`.
pub fn stdlib(&self) -> &Path {
&self.sysconfig.stdlib
}

/// Return the `platstdlib` path for this Python interpreter, as returned by `sysconfig.get_paths()`.
pub fn platstdlib(&self) -> &Path {
&self.sysconfig.platstdlib
}

/// Return the `purelib` path for this Python interpreter, as returned by `sysconfig.get_paths()`.
pub fn purelib(&self) -> &Path {
&self.sysconfig.purelib
}

/// Return the `platlib` path for this Python interpreter, as returned by `sysconfig.get_paths()`.
pub fn platlib(&self) -> &Path {
&self.sysconfig.platlib
}

/// Return the `include` path for this Python interpreter, as returned by `sysconfig.get_paths()`.
pub fn include(&self) -> &Path {
&self.sysconfig.include
}

/// Return the `platinclude` path for this Python interpreter, as returned by `sysconfig.get_paths()`.
pub fn platinclude(&self) -> &Path {
&self.sysconfig.platinclude
}

/// Return the `scripts` path for this Python interpreter, as returned by `sysconfig.get_paths()`.
pub fn scripts(&self) -> &Path {
&self.sysconfig.scripts
}

/// Return the `data` path for this Python interpreter, as returned by `sysconfig.get_paths()`.
pub fn data(&self) -> &Path {
&self.sysconfig.data
}
}

/// The installation paths returned by `sysconfig.get_paths()`.
///
/// See: <https://docs.python.org/3.12/library/sysconfig.html#installation-paths>
#[derive(Debug, Deserialize, Serialize, Clone)]
pub(crate) struct Sysconfig {
pub(crate) stdlib: PathBuf,
pub(crate) platstdlib: PathBuf,
pub(crate) purelib: PathBuf,
pub(crate) platlib: PathBuf,
pub(crate) include: PathBuf,
pub(crate) platinclude: PathBuf,
pub(crate) scripts: PathBuf,
pub(crate) data: PathBuf,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub(crate) struct InterpreterInfo {
pub(crate) markers: MarkerEnvironment,
pub(crate) sysconfig: Sysconfig,
pub(crate) base_exec_prefix: PathBuf,
pub(crate) base_prefix: PathBuf,
pub(crate) stdlib: PathBuf,
pub(crate) sys_executable: PathBuf,
}

Expand Down
16 changes: 0 additions & 16 deletions crates/uv-interpreter/src/python_platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,6 @@ impl PythonPlatform {
venv.join("bin")
}
}

/// Returns the path to the `site-packages` directory inside a virtual environment.
pub(crate) fn venv_site_packages(
&self,
venv_root: impl AsRef<Path>,
version: (u8, u8),
) -> PathBuf {
let venv = venv_root.as_ref();
if matches!(self.0.os(), Os::Windows) {
venv.join("Lib").join("site-packages")
} else {
venv.join("lib")
.join(format!("python{}.{}", version.0, version.1))
.join("site-packages")
}
}
}

impl From<Platform> for PythonPlatform {
Expand Down
37 changes: 20 additions & 17 deletions crates/uv-interpreter/src/virtual_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ pub struct Virtualenv {
}

impl Virtualenv {
/// Create a new virtual environment for a pre-provided Python interpreter.
pub fn from_python(python: PathBuf, platform: &Platform, cache: &Cache) -> Result<Self, Error> {
let interpreter = Interpreter::query(&python, &platform, cache)?;
Ok(Self {
root: interpreter.base_prefix.clone(),
interpreter,
})
}

/// Venv the current Python executable from the host environment.
pub fn from_env(platform: Platform, cache: &Cache) -> Result<Self, Error> {
let platform = PythonPlatform::from(platform);
Expand Down Expand Up @@ -51,15 +60,16 @@ impl Virtualenv {
}
}

/// Returns the location of the python interpreter
pub fn python_executable(&self) -> PathBuf {
self.bin_dir().join(format!("python{EXE_SUFFIX}"))
}

/// Returns the location of the Python interpreter.
pub fn root(&self) -> &Path {
&self.root
}

/// Returns the location of the Python executable.
pub fn python_executable(&self) -> PathBuf {
self.bin_dir().join(format!("python{EXE_SUFFIX}"))
}

/// Return the [`Interpreter`] for this virtual environment.
pub fn interpreter(&self) -> &Interpreter {
&self.interpreter
Expand All @@ -72,20 +82,13 @@ impl Virtualenv {
}

/// Returns the path to the `site-packages` directory inside a virtual environment.
pub fn site_packages(&self) -> PathBuf {
self.interpreter
.platform
.venv_site_packages(&self.root, self.interpreter().python_tuple())
pub fn site_packages(&self) -> &Path {
self.interpreter.platlib()
}

pub fn bin_dir(&self) -> PathBuf {
if cfg!(unix) {
self.root().join("bin")
} else if cfg!(windows) {
self.root().join("Scripts")
} else {
unimplemented!("Only Windows and Unix are supported")
}
/// Returns the path to the `bin` directory inside a virtual environment.
pub fn bin_dir(&self) -> &Path {
self.interpreter.scripts()
}

/// Lock the virtual environment to prevent concurrent writes.
Expand Down
9 changes: 1 addition & 8 deletions crates/uv-resolver/tests/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,7 @@ async fn resolve(
let client = RegistryClientBuilder::new(Cache::temp()?).build();
let flat_index = FlatIndex::default();
let index = InMemoryIndex::default();
let interpreter = Interpreter::artificial(
Platform::current()?,
markers.clone(),
PathBuf::from("/dev/null"),
PathBuf::from("/dev/null"),
PathBuf::from("/dev/null"),
PathBuf::from("/dev/null"),
);
let interpreter = Interpreter::artificial(Platform::current()?, markers.clone());
let build_context = DummyContext::new(Cache::temp()?, interpreter.clone());
let resolver = Resolver::new(
manifest,
Expand Down
9 changes: 7 additions & 2 deletions crates/uv/src/commands/pip_install.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::HashSet;
use std::fmt::Write;

use std::path::Path;
use std::path::{Path, PathBuf};

use anstream::eprint;
use anyhow::{anyhow, Context, Result};
Expand Down Expand Up @@ -63,6 +63,7 @@ pub(crate) async fn pip_install(
no_binary: &NoBinary,
strict: bool,
exclude_newer: Option<DateTime<Utc>>,
python: Option<PathBuf>,
cache: Cache,
mut printer: Printer,
) -> Result<ExitStatus> {
Expand Down Expand Up @@ -105,7 +106,11 @@ pub(crate) async fn pip_install(

// Detect the current Python interpreter.
let platform = Platform::current()?;
let venv = Virtualenv::from_env(platform, &cache)?;
let venv = if let Some(python) = python {
Virtualenv::from_python(python, &platform, &cache)?
} else {
Virtualenv::from_env(platform, &cache)?
};
debug!(
"Using Python {} environment at {}",
venv.interpreter().python_version(),
Expand Down
8 changes: 7 additions & 1 deletion crates/uv/src/commands/pip_sync.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt::Write;
use std::path::PathBuf;

use anyhow::{Context, Result};
use itertools::Itertools;
Expand Down Expand Up @@ -42,6 +43,7 @@ pub(crate) async fn pip_sync(
no_build: &NoBuild,
no_binary: &NoBinary,
strict: bool,
python: Option<PathBuf>,
cache: Cache,
mut printer: Printer,
) -> Result<ExitStatus> {
Expand Down Expand Up @@ -73,7 +75,11 @@ pub(crate) async fn pip_sync(

// Detect the current Python interpreter.
let platform = Platform::current()?;
let venv = Virtualenv::from_env(platform, &cache)?;
let venv = if let Some(python) = python {
Virtualenv::from_python(python, &platform, &cache)?
} else {
Virtualenv::from_env(platform, &cache)?
};
debug!(
"Using Python {} environment at {}",
venv.interpreter().python_version(),
Expand Down
8 changes: 7 additions & 1 deletion crates/uv/src/commands/pip_uninstall.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::fmt::Write;
use std::path::PathBuf;

use anyhow::Result;
use owo_colors::OwoColorize;
Expand All @@ -17,6 +18,7 @@ use crate::requirements::{RequirementsSource, RequirementsSpecification};
/// Uninstall packages from the current environment.
pub(crate) async fn pip_uninstall(
sources: &[RequirementsSource],
python: Option<PathBuf>,
cache: Cache,
mut printer: Printer,
) -> Result<ExitStatus> {
Expand All @@ -38,7 +40,11 @@ pub(crate) async fn pip_uninstall(

// Detect the current Python interpreter.
let platform = Platform::current()?;
let venv = Virtualenv::from_env(platform, &cache)?;
let venv = if let Some(python) = python {
Virtualenv::from_python(python, &platform, &cache)?
} else {
Virtualenv::from_env(platform, &cache)?
};
debug!(
"Using Python {} environment at {}",
venv.interpreter().python_version(),
Expand Down
Loading

0 comments on commit 4a086a3

Please sign in to comment.