Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Support system-site-packages access when create venv #937

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ _Unreleased_

- Always create `.gitignore` file in `rye init`. #919

- Added new `rye.tool.system-site-packages` config, so that the virtualenv
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be tool.rye. (and so on)

can be created with access to the system site packages. #925

<!-- released start -->

## 0.31.0
Expand Down
12 changes: 10 additions & 2 deletions rye/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::piptools::LATEST_PIP;
use crate::platform::{
get_app_dir, get_canonical_py_path, get_toolchain_python_bin, list_known_toolchains,
};
use crate::pyproject::latest_available_python_version;
use crate::pyproject::{latest_available_python_version, PyProject};
use crate::sources::py::{get_download_url, PythonVersion, PythonVersionRequest};
use crate::utils::{check_checksum, symlink_file, unpack_archive, CommandOutput, IoPathContext};
use crate::uv::UvBuilder;
Expand Down Expand Up @@ -142,6 +142,8 @@ pub fn ensure_self_venv_with_toolchain(

let py_bin = get_toolchain_python_bin(&version)?;

let pyproject = PyProject::discover()?;

// linux specific detection of shared libraries.
#[cfg(target_os = "linux")]
{
Expand All @@ -150,7 +152,13 @@ pub fn ensure_self_venv_with_toolchain(

// initialize the virtualenv
{
let uv_venv = uv.venv(&venv_dir, &py_bin, &version, None)?;
let uv_venv = uv.venv(
&venv_dir,
&py_bin,
&version,
None,
pyproject.system_site_packages(),
)?;
// write our marker
uv_venv.write_marker()?;
// update pip and our requirements
Expand Down
9 changes: 8 additions & 1 deletion rye/src/cli/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,12 +452,19 @@ fn resolve_requirements_with_uv(
let venv_path = pyproject_toml.venv_path();
let py_bin = get_venv_python_bin(&venv_path);
let sources = ExpandedSources::from_sources(&pyproject_toml.sources()?)?;
let pyproject = PyProject::discover()?;

let uv = UvBuilder::new()
.with_output(output.quieter())
.with_sources(sources)
.ensure_exists()?
.venv(&venv_path, &py_bin, py_ver, None)?;
.venv(
&venv_path,
&py_bin,
py_ver,
None,
pyproject.system_site_packages(),
)?;

for req in requirements {
let mut new_req = uv.resolve(py_ver, req, pre, env::var("__RYE_UV_EXCLUDE_NEWER").ok())?;
Expand Down
1 change: 1 addition & 0 deletions rye/src/cli/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub fn execute(cmd: Args) -> Result<(), Error> {
&python,
&project.venv_python_version()?,
None,
project.system_site_packages(),
)?
.freeze()?;
} else {
Expand Down
5 changes: 3 additions & 2 deletions rye/src/installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,15 @@ pub fn install(
&py_ver,
&target_venv_path,
requirement.name.as_str(),
false,
)?;

if Config::current().use_uv() {
if config.use_uv() {
let result = UvBuilder::new()
.with_output(output.quieter())
.with_sources(sources)
.ensure_exists()?
.venv(&target_venv_path, &py, &py_ver, None)?
.venv(&target_venv_path, &py, &py_ver, None, false)?
.with_output(output)
.install(
&requirement,
Expand Down
2 changes: 1 addition & 1 deletion rye/src/piptools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fn get_pip_tools_bin(py_ver: &PythonVersion, output: CommandOutput) -> Result<Pa
}

echo!(if output, "Creating virtualenv for pip-tools");
create_virtualenv(output, &self_venv, py_ver, &venv, "pip-tools")?;
create_virtualenv(output, &self_venv, py_ver, &venv, "pip-tools", false)?;

let mut cmd = Command::new(self_venv.join(VENV_BIN).join("pip"));
cmd.arg("--python")
Expand Down
21 changes: 21 additions & 0 deletions rye/src/pyproject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,11 @@ impl Workspace {
pub fn lock_with_sources(&self) -> bool {
lock_with_sources(&self.doc)
}

/// Include system site packages when creating virtualenvs?
pub fn system_site_packages(&self) -> bool {
system_site_packages(&self.doc)
}
}

/// Check if recurse should be skipped into directory with this name
Expand Down Expand Up @@ -1005,6 +1010,14 @@ impl PyProject {
}
}

/// Include system site packages when creating virtualenvs?
pub fn system_site_packages(&self) -> bool {
match self.workspace {
Some(ref workspace) => workspace.system_site_packages(),
None => system_site_packages(&self.doc),
}
}

/// Save back changes
pub fn save(&self) -> Result<(), Error> {
let path = self.toml_path();
Expand Down Expand Up @@ -1279,6 +1292,14 @@ fn lock_with_sources(doc: &Document) -> bool {
.unwrap_or(false)
}

fn system_site_packages(doc: &Document) -> bool {
doc.get("tool")
.and_then(|x| x.get("rye"))
.and_then(|x| x.get("system-site-packages"))
.and_then(|x| x.as_bool())
.unwrap_or(false)
}

fn get_project_metadata(path: &Path) -> Result<Metadata, Error> {
let self_venv = ensure_self_venv(CommandOutput::Normal)?;
let mut metadata = Command::new(self_venv.join(VENV_BIN).join("python"));
Expand Down
22 changes: 18 additions & 4 deletions rye/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,15 @@ pub fn sync(mut cmd: SyncOptions) -> Result<(), Error> {
);
echo!(if output, "Python version: {}", style(&py_ver).cyan());
let prompt = pyproject.name().unwrap_or("venv");
create_virtualenv(output, &self_venv, &py_ver, &venv, prompt)
.context("failed creating virtualenv ahead of sync")?;
create_virtualenv(
output,
&self_venv,
&py_ver,
&venv,
prompt,
pyproject.system_site_packages(),
)
.context("failed creating virtualenv ahead of sync")?;
}

// prepare necessary utilities for pip-sync. This is a super crude
Expand Down Expand Up @@ -251,7 +258,13 @@ pub fn sync(mut cmd: SyncOptions) -> Result<(), Error> {
.with_workdir(&pyproject.workspace_path())
.with_sources(sources)
.ensure_exists()?
.venv(&venv, &py_path, &py_ver, None)?
.venv(
&venv,
&py_path,
&py_ver,
None,
pyproject.system_site_packages(),
)?
.with_output(output)
.sync(&target_lockfile)?;
} else {
Expand Down Expand Up @@ -328,6 +341,7 @@ pub fn create_virtualenv(
py_ver: &PythonVersion,
venv: &Path,
prompt: &str,
system_site_packages: bool,
) -> Result<(), Error> {
let py_bin = get_toolchain_python_bin(py_ver)?;

Expand All @@ -337,7 +351,7 @@ pub fn create_virtualenv(
let uv = UvBuilder::new()
.with_output(output.quieter())
.ensure_exists()?
.venv(venv, &py_bin, py_ver, Some(prompt))
.venv(venv, &py_bin, py_ver, Some(prompt), system_site_packages)
.context("failed to initialize virtualenv")?;
uv.write_marker()?;
uv.sync_marker();
Expand Down
7 changes: 6 additions & 1 deletion rye/src/uv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,13 @@ impl Uv {
py_bin: &Path,
version: &PythonVersion,
prompt: Option<&str>,
system_site_packages: bool,
) -> Result<UvWithVenv, Error> {
match read_venv_marker(venv_dir) {
Some(venv) if venv.is_compatible(version) => {
Ok(UvWithVenv::new(self.clone(), venv_dir, version))
}
_ => self.create_venv(venv_dir, py_bin, version, prompt),
_ => self.create_venv(venv_dir, py_bin, version, prompt, system_site_packages),
}
}

Expand All @@ -277,12 +278,16 @@ impl Uv {
py_bin: &Path,
version: &PythonVersion,
prompt: Option<&str>,
system_site_packages: bool,
) -> Result<UvWithVenv, Error> {
let mut cmd = self.cmd();
cmd.arg("venv").arg("--python").arg(py_bin);
if let Some(prompt) = prompt {
cmd.arg("--prompt").arg(prompt);
}
if system_site_packages {
cmd.arg("--system-site-packages");
}
cmd.arg(venv_dir);
let status = cmd.status().with_context(|| {
format!(
Expand Down
19 changes: 17 additions & 2 deletions rye/tests/test_sync.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::fs;

use insta::{assert_snapshot, Settings};

use crate::common::{rye_cmd_snapshot, Space};
use insta::{assert_snapshot, Settings};
use toml_edit::value;

mod common;

Expand Down Expand Up @@ -261,3 +261,18 @@ fn test_autosync_remember() {
werkzeug==3.0.1
"###);
}

#[test]
fn test_sync_include_system_site_packages() {
let space = Space::new();
space.init("my-project");
space.edit_toml("pyproject.toml", |doc| {
doc["tool"]["rye"]["system-site-packages"] = value(true);
});

space.rye_cmd().arg("sync").status().expect("ok");

assert!(fs::read_to_string(space.venv_path().join("pyvenv.cfg"))
.unwrap()
.contains("include-system-site-packages = true"));
}