Rename gourgeist to uv-virtualenv (#2118)

As agreed on Discord!
This commit is contained in:
Charlie Marsh 2024-03-01 14:02:40 -05:00 committed by GitHub
parent b818199403
commit 59c7a10c4b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 65 additions and 184 deletions

56
Cargo.lock generated
View file

@ -1276,29 +1276,6 @@ dependencies = [
"scroll", "scroll",
] ]
[[package]]
name = "gourgeist"
version = "0.0.4"
dependencies = [
"anstream",
"cachedir",
"camino",
"clap",
"directories",
"fs-err",
"platform-host",
"serde",
"serde_json",
"tempfile",
"thiserror",
"tracing",
"tracing-subscriber",
"uv-cache",
"uv-fs",
"uv-interpreter",
"which",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.3.24" version = "0.3.24"
@ -4152,7 +4129,6 @@ dependencies = [
"flate2", "flate2",
"fs-err", "fs-err",
"futures", "futures",
"gourgeist",
"indexmap 2.2.3", "indexmap 2.2.3",
"indicatif", "indicatif",
"indoc", "indoc",
@ -4199,6 +4175,7 @@ dependencies = [
"uv-normalize", "uv-normalize",
"uv-resolver", "uv-resolver",
"uv-traits", "uv-traits",
"uv-virtualenv",
"uv-warnings", "uv-warnings",
"which", "which",
] ]
@ -4218,7 +4195,6 @@ dependencies = [
"anyhow", "anyhow",
"distribution-types", "distribution-types",
"fs-err", "fs-err",
"gourgeist",
"indoc", "indoc",
"insta", "insta",
"itertools 0.12.1", "itertools 0.12.1",
@ -4240,6 +4216,7 @@ dependencies = [
"uv-fs", "uv-fs",
"uv-interpreter", "uv-interpreter",
"uv-traits", "uv-traits",
"uv-virtualenv",
] ]
[[package]] [[package]]
@ -4322,7 +4299,6 @@ dependencies = [
"distribution-types", "distribution-types",
"fs-err", "fs-err",
"futures", "futures",
"gourgeist",
"indicatif", "indicatif",
"install-wheel-rs", "install-wheel-rs",
"itertools 0.12.1", "itertools 0.12.1",
@ -4358,6 +4334,7 @@ dependencies = [
"uv-normalize", "uv-normalize",
"uv-resolver", "uv-resolver",
"uv-traits", "uv-traits",
"uv-virtualenv",
"which", "which",
] ]
@ -4369,7 +4346,6 @@ dependencies = [
"distribution-types", "distribution-types",
"fs-err", "fs-err",
"futures", "futures",
"gourgeist",
"itertools 0.12.1", "itertools 0.12.1",
"pep508_rs", "pep508_rs",
"platform-host", "platform-host",
@ -4387,6 +4363,7 @@ dependencies = [
"uv-interpreter", "uv-interpreter",
"uv-resolver", "uv-resolver",
"uv-traits", "uv-traits",
"uv-virtualenv",
] ]
[[package]] [[package]]
@ -4575,7 +4552,6 @@ dependencies = [
"either", "either",
"fs-err", "fs-err",
"futures", "futures",
"gourgeist",
"indexmap 2.2.3", "indexmap 2.2.3",
"insta", "insta",
"install-wheel-rs", "install-wheel-rs",
@ -4609,6 +4585,7 @@ dependencies = [
"uv-interpreter", "uv-interpreter",
"uv-normalize", "uv-normalize",
"uv-traits", "uv-traits",
"uv-virtualenv",
"uv-warnings", "uv-warnings",
"zip", "zip",
] ]
@ -4630,6 +4607,29 @@ dependencies = [
"uv-normalize", "uv-normalize",
] ]
[[package]]
name = "uv-virtualenv"
version = "0.0.4"
dependencies = [
"anstream",
"cachedir",
"camino",
"clap",
"directories",
"fs-err",
"platform-host",
"serde",
"serde_json",
"tempfile",
"thiserror",
"tracing",
"tracing-subscriber",
"uv-cache",
"uv-fs",
"uv-interpreter",
"which",
]
[[package]] [[package]]
name = "uv-warnings" name = "uv-warnings"
version = "0.0.1" version = "0.0.1"

View file

@ -18,10 +18,6 @@ metadata.
Abstractions for representing built distributions (wheels) and source distributions (sdists), and Abstractions for representing built distributions (wheels) and source distributions (sdists), and
the sources from which they can be downloaded. the sources from which they can be downloaded.
## [gourgeist](./gourgeist)
A `venv` replacement to create virtual environments in Rust.
## [install-wheel-rs](./install-wheel-rs) ## [install-wheel-rs](./install-wheel-rs)
Install built distributions (wheels) into a virtual environment.] Install built distributions (wheels) into a virtual environment.]
@ -117,6 +113,10 @@ Shared traits for uv, to avoid circular dependencies.
General-purpose type definitions for types used in PyPI-compatible APIs. General-purpose type definitions for types used in PyPI-compatible APIs.
## [uv-virtualenv](./uv-virtualenv)
A `venv` replacement to create virtual environments in Rust.
## [uv-warnings](./uv-warnings) ## [uv-warnings](./uv-warnings)
User-facing warnings for uv. User-facing warnings for uv.

View file

@ -1,33 +0,0 @@
# Gourgeist
Gourgeist is a rust library to create python virtual environments. It also has a CLI.
It currently supports only unix (linux/mac), windows support is missing.
## Rust
```rust
use camino::Utf8PathBuf;
use gourgeist::{create_venv, get_interpreter_info, parse_python_cli};
let location = cli.path.unwrap_or(Utf8PathBuf::from(".venv"));
let python = parse_python_cli(cli.python)?;
let data = get_interpreter_info(&python)?;
create_venv(&location, &python, &data, cli.bare)?;
```
## CLI
Use `python` as base for a virtualenv `.venv`:
```bash
gourgeist
```
Or use custom defaults:
```bash
gourgeist -p 3.11 my_env
```
## Jessie's gourgeist
![Jessie's gourgeist, a pokemon with a jack o'lantern as body](static/gourgeist.png)

View file

@ -1,14 +0,0 @@
#!/usr/bin/env bash
set -e
cd "$(git rev-parse --show-toplevel)"
virtualenv --version
cargo build --profile profiling --bin gourgeist --features cli
hyperfine --warmup 1 --shell none --prepare "rm -rf target/venv-benchmark" \
"target/profiling/gourgeist -p 3.11 target/venv-benchmark" \
"virtualenv -p 3.11 --no-seed target/venv-benchmark"

View file

@ -1,27 +0,0 @@
#!/usr/bin/env bash
set -e
virtualenv_command() {
virtualenv -p 3.11 compare_venv # --no-pip --no-setuptools --no-wheel
}
rust_command() {
cargo run -- -p 3.11 compare_venv # --bare
}
rm -rf compare_venv
virtualenv_command
rm compare_venv/.gitignore
git -C compare_venv init
git -C compare_venv add -A
git -C compare_venv commit -q -m "Initial commit"
rm -r compare_venv/* # This skips the hidden .git
mkdir -p target
mv compare_venv target/compare_venv2
rust_command
rm compare_venv/.gitignore
cp -r compare_venv/* target/compare_venv2
rm -r compare_venv
mv target/compare_venv2 compare_venv
git -C compare_venv/ status

View file

@ -1,12 +0,0 @@
import sys
def main():
print(sys.executable)
print(sys.version)
print(sys.base_prefix)
print(sys.prefix)
if __name__ == "__main__":
main()

View file

@ -1,8 +0,0 @@
{
"styles": {
"theme": "axo_light"
},
"build": {
"path_prefix": "gourgeist"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 MiB

View file

@ -1,28 +0,0 @@
from pathlib import Path
from subprocess import check_output, check_call
def main():
project_root = Path(__file__).parent
venv_name = ".venv-rs"
venv_python = f"{venv_name}/bin/python"
venv_pip = f"{venv_name}/bin/pip"
command = f". {venv_name}/bin/activate && which python"
output = check_output(["bash"], input=command, text=True).strip()
assert output == str(project_root.joinpath(venv_python)), output
command = f". {venv_name}/bin/activate && wheel help"
output = check_output(["bash"], input=command, text=True).strip()
assert output.startswith("usage:"), output
output = check_output([venv_python, "imasnake.py"], text=True).strip().splitlines()
assert output[0] == str(project_root.joinpath(venv_python)), output
assert not output[2].startswith(str(project_root)), output
assert output[3] == str(project_root.joinpath(venv_name)), output
check_call([venv_pip, "install", "tqdm"])
if __name__ == "__main__":
main()

View file

@ -15,14 +15,14 @@ workspace = true
[dependencies] [dependencies]
distribution-types = { path = "../distribution-types" } distribution-types = { path = "../distribution-types" }
gourgeist = { path = "../gourgeist" }
pep508_rs = { path = "../pep508-rs" } pep508_rs = { path = "../pep508-rs" }
platform-host = { path = "../platform-host" } platform-host = { path = "../platform-host" }
pypi-types = { path = "../pypi-types" }
uv-extract = { path = "../uv-extract" } uv-extract = { path = "../uv-extract" }
uv-fs = { path = "../uv-fs" } uv-fs = { path = "../uv-fs" }
uv-interpreter = { path = "../uv-interpreter" } uv-interpreter = { path = "../uv-interpreter" }
uv-traits = { path = "../uv-traits", features = ["serde"] } uv-traits = { path = "../uv-traits", features = ["serde"] }
pypi-types = { path = "../pypi-types" } uv-virtualenv = { path = "../uv-virtualenv" }
anyhow = { workspace = true } anyhow = { workspace = true }
fs-err = { workspace = true } fs-err = { workspace = true }

View file

@ -75,7 +75,7 @@ pub enum Error {
#[error("Source distribution not found at: {0}")] #[error("Source distribution not found at: {0}")]
NotFound(PathBuf), NotFound(PathBuf),
#[error("Failed to create temporary virtualenv")] #[error("Failed to create temporary virtualenv")]
Gourgeist(#[from] gourgeist::Error), Virtualenv(#[from] uv_virtualenv::Error),
#[error("Failed to run {0}")] #[error("Failed to run {0}")]
CommandFailed(PathBuf, #[source] io::Error), CommandFailed(PathBuf, #[source] io::Error),
#[error("{message}:\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")] #[error("{message}:\n--- stdout:\n{stdout}\n--- stderr:\n{stderr}\n---")]
@ -398,10 +398,10 @@ impl SourceBuild {
let pep517_backend = Self::get_pep517_backend(setup_py, &source_tree, &default_backend) let pep517_backend = Self::get_pep517_backend(setup_py, &source_tree, &default_backend)
.map_err(|err| *err)?; .map_err(|err| *err)?;
let venv = gourgeist::create_venv( let venv = uv_virtualenv::create_venv(
&temp_dir.path().join(".venv"), &temp_dir.path().join(".venv"),
interpreter.clone(), interpreter.clone(),
gourgeist::Prompt::None, uv_virtualenv::Prompt::None,
false, false,
Vec::new(), Vec::new(),
)?; )?;

View file

@ -18,12 +18,12 @@ workspace = true
[dependencies] [dependencies]
distribution-filename = { path = "../distribution-filename" } distribution-filename = { path = "../distribution-filename" }
distribution-types = { path = "../distribution-types" } distribution-types = { path = "../distribution-types" }
gourgeist = { path = "../gourgeist" }
install-wheel-rs = { path = "../install-wheel-rs" } install-wheel-rs = { path = "../install-wheel-rs" }
pep440_rs = { path = "../pep440-rs" } pep440_rs = { path = "../pep440-rs" }
pep508_rs = { path = "../pep508-rs" } pep508_rs = { path = "../pep508-rs" }
platform-host = { path = "../platform-host" } platform-host = { path = "../platform-host" }
platform-tags = { path = "../platform-tags" } platform-tags = { path = "../platform-tags" }
pypi-types = { path = "../pypi-types" }
uv-build = { path = "../uv-build" } uv-build = { path = "../uv-build" }
uv-cache = { path = "../uv-cache", features = ["clap"] } uv-cache = { path = "../uv-cache", features = ["clap"] }
uv-client = { path = "../uv-client" } uv-client = { path = "../uv-client" }
@ -33,8 +33,8 @@ uv-installer = { path = "../uv-installer" }
uv-interpreter = { path = "../uv-interpreter" } uv-interpreter = { path = "../uv-interpreter" }
uv-normalize = { path = "../uv-normalize" } uv-normalize = { path = "../uv-normalize" }
uv-resolver = { path = "../uv-resolver" } uv-resolver = { path = "../uv-resolver" }
pypi-types = { path = "../pypi-types" }
uv-traits = { path = "../uv-traits" } uv-traits = { path = "../uv-traits" }
uv-virtualenv = { path = "../uv-virtualenv" }
# Any dependencies that are exclusively used in `uv-dev` should be listed as non-workspace # Any dependencies that are exclusively used in `uv-dev` should be listed as non-workspace
# dependencies, to ensure that we're forced to think twice before including them in other crates. # dependencies, to ensure that we're forced to think twice before including them in other crates.

View file

@ -15,10 +15,10 @@ workspace = true
[dependencies] [dependencies]
distribution-types = { path = "../distribution-types" } distribution-types = { path = "../distribution-types" }
gourgeist = { path = "../gourgeist" }
pep508_rs = { path = "../pep508-rs" } pep508_rs = { path = "../pep508-rs" }
platform-host = { path = "../platform-host" } platform-host = { path = "../platform-host" }
platform-tags = { path = "../platform-tags" } platform-tags = { path = "../platform-tags" }
pypi-types = { path = "../pypi-types" }
uv-build = { path = "../uv-build" } uv-build = { path = "../uv-build" }
uv-cache = { path = "../uv-cache" } uv-cache = { path = "../uv-cache" }
uv-client = { path = "../uv-client" } uv-client = { path = "../uv-client" }
@ -27,13 +27,13 @@ uv-installer = { path = "../uv-installer" }
uv-interpreter = { path = "../uv-interpreter" } uv-interpreter = { path = "../uv-interpreter" }
uv-resolver = { path = "../uv-resolver" } uv-resolver = { path = "../uv-resolver" }
uv-traits = { path = "../uv-traits" } uv-traits = { path = "../uv-traits" }
pypi-types = { path = "../pypi-types" } uv-virtualenv = { path = "../uv-virtualenv" }
rustc-hash = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
fs-err = { workspace = true } fs-err = { workspace = true }
futures = { workspace = true } futures = { workspace = true }
itertools = { workspace = true } itertools = { workspace = true }
rustc-hash = { workspace = true }
tempfile = { workspace = true } tempfile = { workspace = true }
tokio = { workspace = true } tokio = { workspace = true }
tracing = { workspace = true } tracing = { workspace = true }

View file

@ -22,6 +22,7 @@ pep440_rs = { path = "../pep440-rs", features = ["pubgrub"] }
pep508_rs = { path = "../pep508-rs" } pep508_rs = { path = "../pep508-rs" }
platform-host = { path = "../platform-host" } platform-host = { path = "../platform-host" }
platform-tags = { path = "../platform-tags" } platform-tags = { path = "../platform-tags" }
pypi-types = { path = "../pypi-types" }
uv-cache = { path = "../uv-cache" } uv-cache = { path = "../uv-cache" }
uv-client = { path = "../uv-client" } uv-client = { path = "../uv-client" }
uv-distribution = { path = "../uv-distribution" } uv-distribution = { path = "../uv-distribution" }
@ -30,7 +31,6 @@ uv-interpreter = { path = "../uv-interpreter" }
uv-normalize = { path = "../uv-normalize" } uv-normalize = { path = "../uv-normalize" }
uv-traits = { path = "../uv-traits" } uv-traits = { path = "../uv-traits" }
uv-warnings = { path = "../uv-warnings" } uv-warnings = { path = "../uv-warnings" }
pypi-types = { path = "../pypi-types" }
anstream = { workspace = true } anstream = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }
@ -62,7 +62,7 @@ url = { workspace = true }
zip = { workspace = true } zip = { workspace = true }
[dev-dependencies] [dev-dependencies]
gourgeist = { path = "../gourgeist" } uv-virtualenv = { path = "../uv-virtualenv" }
uv-interpreter = { path = "../uv-interpreter" } uv-interpreter = { path = "../uv-interpreter" }
once_cell = { version = "1.19.0" } once_cell = { version = "1.19.0" }

View file

@ -1,5 +1,5 @@
[package] [package]
name = "gourgeist" name = "uv-virtualenv"
version = "0.0.4" version = "0.0.4"
publish = false publish = false
description = "virtualenv creation implemented in rust" description = "virtualenv creation implemented in rust"
@ -14,7 +14,7 @@ authors = { workspace = true }
license = { workspace = true } license = { workspace = true }
[[bin]] [[bin]]
name = "gourgeist" name = "uv-virtualenv"
required-features = ["cli"] required-features = ["cli"]
[lints] [lints]

View file

@ -0,0 +1,3 @@
# uv-virtualenv
`uv-virtualenv` is a rust library to create Python virtual environments. It also has a CLI.

View file

@ -11,10 +11,10 @@ use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt; use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{fmt, EnvFilter}; use tracing_subscriber::{fmt, EnvFilter};
use gourgeist::{create_bare_venv, Prompt};
use platform_host::Platform; use platform_host::Platform;
use uv_cache::Cache; use uv_cache::Cache;
use uv_interpreter::{find_default_python, find_requested_python}; use uv_interpreter::{find_default_python, find_requested_python};
use uv_virtualenv::{create_bare_venv, Prompt};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Cli { struct Cli {
@ -27,14 +27,14 @@ struct Cli {
system_site_packages: bool, system_site_packages: bool,
} }
fn run() -> Result<(), gourgeist::Error> { fn run() -> Result<(), uv_virtualenv::Error> {
let cli = Cli::parse(); let cli = Cli::parse();
let location = cli.path.unwrap_or(Utf8PathBuf::from(".venv")); let location = cli.path.unwrap_or(Utf8PathBuf::from(".venv"));
let platform = Platform::current()?; let platform = Platform::current()?;
let cache = if let Some(project_dirs) = ProjectDirs::from("", "", "gourgeist") { let cache = if let Some(project_dirs) = ProjectDirs::from("", "", "uv-virtualenv") {
Cache::from_path(project_dirs.cache_dir())? Cache::from_path(project_dirs.cache_dir())?
} else { } else {
Cache::from_path(".gourgeist_cache")? Cache::from_path(".cache")?
}; };
let interpreter = if let Some(python_request) = &cli.python { let interpreter = if let Some(python_request) = &cli.python {
find_requested_python(python_request, &platform, &cache)?.ok_or( find_requested_python(python_request, &platform, &cache)?.ok_or(

View file

@ -16,12 +16,13 @@ workspace = true
[dependencies] [dependencies]
distribution-filename = { path = "../distribution-filename" } distribution-filename = { path = "../distribution-filename" }
distribution-types = { path = "../distribution-types" } distribution-types = { path = "../distribution-types" }
gourgeist = { path = "../gourgeist" }
install-wheel-rs = { path = "../install-wheel-rs", features = ["clap"], default-features = false } install-wheel-rs = { path = "../install-wheel-rs", features = ["clap"], default-features = false }
pep440_rs = { path = "../pep440-rs" } pep440_rs = { path = "../pep440-rs" }
pep508_rs = { path = "../pep508-rs" } pep508_rs = { path = "../pep508-rs" }
platform-host = { path = "../platform-host" } platform-host = { path = "../platform-host" }
platform-tags = { path = "../platform-tags" } platform-tags = { path = "../platform-tags" }
pypi-types = { path = "../pypi-types" }
requirements-txt = { path = "../requirements-txt" }
uv-build = { path = "../uv-build" } uv-build = { path = "../uv-build" }
uv-cache = { path = "../uv-cache", features = ["clap"] } uv-cache = { path = "../uv-cache", features = ["clap"] }
uv-client = { path = "../uv-client" } uv-client = { path = "../uv-client" }
@ -33,9 +34,8 @@ uv-interpreter = { path = "../uv-interpreter" }
uv-normalize = { path = "../uv-normalize" } uv-normalize = { path = "../uv-normalize" }
uv-resolver = { path = "../uv-resolver", features = ["clap"] } uv-resolver = { path = "../uv-resolver", features = ["clap"] }
uv-traits = { path = "../uv-traits" } uv-traits = { path = "../uv-traits" }
uv-virtualenv = { path = "../uv-virtualenv" }
uv-warnings = { path = "../uv-warnings" } uv-warnings = { path = "../uv-warnings" }
pypi-types = { path = "../pypi-types" }
requirements-txt = { path = "../requirements-txt" }
anstream = { workspace = true } anstream = { workspace = true }
anyhow = { workspace = true } anyhow = { workspace = true }

View file

@ -12,7 +12,6 @@ use owo_colors::OwoColorize;
use thiserror::Error; use thiserror::Error;
use distribution_types::{DistributionMetadata, IndexLocations, Name}; use distribution_types::{DistributionMetadata, IndexLocations, Name};
use gourgeist::Prompt;
use pep508_rs::Requirement; use pep508_rs::Requirement;
use platform_host::Platform; use platform_host::Platform;
use uv_cache::Cache; use uv_cache::Cache;
@ -33,7 +32,7 @@ pub(crate) async fn venv(
path: &Path, path: &Path,
python_request: Option<&str>, python_request: Option<&str>,
index_locations: &IndexLocations, index_locations: &IndexLocations,
prompt: Prompt, prompt: uv_virtualenv::Prompt,
system_site_packages: bool, system_site_packages: bool,
connectivity: Connectivity, connectivity: Connectivity,
seed: bool, seed: bool,
@ -67,7 +66,7 @@ pub(crate) async fn venv(
enum VenvError { enum VenvError {
#[error("Failed to create virtualenv")] #[error("Failed to create virtualenv")]
#[diagnostic(code(uv::venv::creation))] #[diagnostic(code(uv::venv::creation))]
Creation(#[source] gourgeist::Error), Creation(#[source] uv_virtualenv::Error),
#[error("Failed to install seed packages")] #[error("Failed to install seed packages")]
#[diagnostic(code(uv::venv::seed))] #[diagnostic(code(uv::venv::seed))]
@ -88,7 +87,7 @@ async fn venv_impl(
path: &Path, path: &Path,
python_request: Option<&str>, python_request: Option<&str>,
index_locations: &IndexLocations, index_locations: &IndexLocations,
prompt: Prompt, prompt: uv_virtualenv::Prompt,
system_site_packages: bool, system_site_packages: bool,
connectivity: Connectivity, connectivity: Connectivity,
seed: bool, seed: bool,
@ -126,8 +125,9 @@ async fn venv_impl(
let extra_cfg = vec![("uv".to_string(), env!("CARGO_PKG_VERSION").to_string())]; let extra_cfg = vec![("uv".to_string(), env!("CARGO_PKG_VERSION").to_string())];
// Create the virtual environment. // Create the virtual environment.
let venv = gourgeist::create_venv(path, interpreter, prompt, system_site_packages, extra_cfg) let venv =
.map_err(VenvError::Creation)?; uv_virtualenv::create_venv(path, interpreter, prompt, system_site_packages, extra_cfg)
.map_err(VenvError::Creation)?;
// Install seed packages. // Install seed packages.
if seed { if seed {

View file

@ -1397,7 +1397,7 @@ async fn run() -> Result<ExitStatus> {
&args.name, &args.name,
args.python.as_deref(), args.python.as_deref(),
&index_locations, &index_locations,
gourgeist::Prompt::from_args(prompt), uv_virtualenv::Prompt::from_args(prompt),
args.system_site_packages, args.system_site_packages,
if args.offline { if args.offline {
Connectivity::Offline Connectivity::Offline

View file

@ -1,6 +1,6 @@
exclude = [ exclude = [
"crates/gourgeist/src/activator/activate_this.py", "crates/uv-virtualenv/src/activator/activate_this.py",
"crates/gourgeist/src/_virtualenv.py" "crates/uv-virtualenv/src/_virtualenv.py"
] ]
[lint.per-file-ignores] [lint.per-file-ignores]
"__init__.py" = ["F403", "F405"] "__init__.py" = ["F403", "F405"]