mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-07 13:25:00 +00:00
parent
b818199403
commit
59c7a10c4b
35 changed files with 65 additions and 184 deletions
56
Cargo.lock
generated
56
Cargo.lock
generated
|
@ -1276,29 +1276,6 @@ dependencies = [
|
|||
"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]]
|
||||
name = "h2"
|
||||
version = "0.3.24"
|
||||
|
@ -4152,7 +4129,6 @@ dependencies = [
|
|||
"flate2",
|
||||
"fs-err",
|
||||
"futures",
|
||||
"gourgeist",
|
||||
"indexmap 2.2.3",
|
||||
"indicatif",
|
||||
"indoc",
|
||||
|
@ -4199,6 +4175,7 @@ dependencies = [
|
|||
"uv-normalize",
|
||||
"uv-resolver",
|
||||
"uv-traits",
|
||||
"uv-virtualenv",
|
||||
"uv-warnings",
|
||||
"which",
|
||||
]
|
||||
|
@ -4218,7 +4195,6 @@ dependencies = [
|
|||
"anyhow",
|
||||
"distribution-types",
|
||||
"fs-err",
|
||||
"gourgeist",
|
||||
"indoc",
|
||||
"insta",
|
||||
"itertools 0.12.1",
|
||||
|
@ -4240,6 +4216,7 @@ dependencies = [
|
|||
"uv-fs",
|
||||
"uv-interpreter",
|
||||
"uv-traits",
|
||||
"uv-virtualenv",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4322,7 +4299,6 @@ dependencies = [
|
|||
"distribution-types",
|
||||
"fs-err",
|
||||
"futures",
|
||||
"gourgeist",
|
||||
"indicatif",
|
||||
"install-wheel-rs",
|
||||
"itertools 0.12.1",
|
||||
|
@ -4358,6 +4334,7 @@ dependencies = [
|
|||
"uv-normalize",
|
||||
"uv-resolver",
|
||||
"uv-traits",
|
||||
"uv-virtualenv",
|
||||
"which",
|
||||
]
|
||||
|
||||
|
@ -4369,7 +4346,6 @@ dependencies = [
|
|||
"distribution-types",
|
||||
"fs-err",
|
||||
"futures",
|
||||
"gourgeist",
|
||||
"itertools 0.12.1",
|
||||
"pep508_rs",
|
||||
"platform-host",
|
||||
|
@ -4387,6 +4363,7 @@ dependencies = [
|
|||
"uv-interpreter",
|
||||
"uv-resolver",
|
||||
"uv-traits",
|
||||
"uv-virtualenv",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4575,7 +4552,6 @@ dependencies = [
|
|||
"either",
|
||||
"fs-err",
|
||||
"futures",
|
||||
"gourgeist",
|
||||
"indexmap 2.2.3",
|
||||
"insta",
|
||||
"install-wheel-rs",
|
||||
|
@ -4609,6 +4585,7 @@ dependencies = [
|
|||
"uv-interpreter",
|
||||
"uv-normalize",
|
||||
"uv-traits",
|
||||
"uv-virtualenv",
|
||||
"uv-warnings",
|
||||
"zip",
|
||||
]
|
||||
|
@ -4630,6 +4607,29 @@ dependencies = [
|
|||
"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]]
|
||||
name = "uv-warnings"
|
||||
version = "0.0.1"
|
||||
|
|
|
@ -18,10 +18,6 @@ metadata.
|
|||
Abstractions for representing built distributions (wheels) and source distributions (sdists), and
|
||||
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 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.
|
||||
|
||||
## [uv-virtualenv](./uv-virtualenv)
|
||||
|
||||
A `venv` replacement to create virtual environments in Rust.
|
||||
|
||||
## [uv-warnings](./uv-warnings)
|
||||
|
||||
User-facing warnings for uv.
|
||||
|
|
|
@ -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
|
||||
|
||||

|
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"styles": {
|
||||
"theme": "axo_light"
|
||||
},
|
||||
"build": {
|
||||
"path_prefix": "gourgeist"
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 1 MiB |
|
@ -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()
|
|
@ -15,14 +15,14 @@ workspace = true
|
|||
|
||||
[dependencies]
|
||||
distribution-types = { path = "../distribution-types" }
|
||||
gourgeist = { path = "../gourgeist" }
|
||||
pep508_rs = { path = "../pep508-rs" }
|
||||
platform-host = { path = "../platform-host" }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
uv-extract = { path = "../uv-extract" }
|
||||
uv-fs = { path = "../uv-fs" }
|
||||
uv-interpreter = { path = "../uv-interpreter" }
|
||||
uv-traits = { path = "../uv-traits", features = ["serde"] }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
uv-virtualenv = { path = "../uv-virtualenv" }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
fs-err = { workspace = true }
|
||||
|
|
|
@ -75,7 +75,7 @@ pub enum Error {
|
|||
#[error("Source distribution not found at: {0}")]
|
||||
NotFound(PathBuf),
|
||||
#[error("Failed to create temporary virtualenv")]
|
||||
Gourgeist(#[from] gourgeist::Error),
|
||||
Virtualenv(#[from] uv_virtualenv::Error),
|
||||
#[error("Failed to run {0}")]
|
||||
CommandFailed(PathBuf, #[source] io::Error),
|
||||
#[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)
|
||||
.map_err(|err| *err)?;
|
||||
|
||||
let venv = gourgeist::create_venv(
|
||||
let venv = uv_virtualenv::create_venv(
|
||||
&temp_dir.path().join(".venv"),
|
||||
interpreter.clone(),
|
||||
gourgeist::Prompt::None,
|
||||
uv_virtualenv::Prompt::None,
|
||||
false,
|
||||
Vec::new(),
|
||||
)?;
|
||||
|
|
|
@ -18,12 +18,12 @@ workspace = true
|
|||
[dependencies]
|
||||
distribution-filename = { path = "../distribution-filename" }
|
||||
distribution-types = { path = "../distribution-types" }
|
||||
gourgeist = { path = "../gourgeist" }
|
||||
install-wheel-rs = { path = "../install-wheel-rs" }
|
||||
pep440_rs = { path = "../pep440-rs" }
|
||||
pep508_rs = { path = "../pep508-rs" }
|
||||
platform-host = { path = "../platform-host" }
|
||||
platform-tags = { path = "../platform-tags" }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
uv-build = { path = "../uv-build" }
|
||||
uv-cache = { path = "../uv-cache", features = ["clap"] }
|
||||
uv-client = { path = "../uv-client" }
|
||||
|
@ -33,8 +33,8 @@ uv-installer = { path = "../uv-installer" }
|
|||
uv-interpreter = { path = "../uv-interpreter" }
|
||||
uv-normalize = { path = "../uv-normalize" }
|
||||
uv-resolver = { path = "../uv-resolver" }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
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
|
||||
# dependencies, to ensure that we're forced to think twice before including them in other crates.
|
||||
|
|
|
@ -15,10 +15,10 @@ workspace = true
|
|||
|
||||
[dependencies]
|
||||
distribution-types = { path = "../distribution-types" }
|
||||
gourgeist = { path = "../gourgeist" }
|
||||
pep508_rs = { path = "../pep508-rs" }
|
||||
platform-host = { path = "../platform-host" }
|
||||
platform-tags = { path = "../platform-tags" }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
uv-build = { path = "../uv-build" }
|
||||
uv-cache = { path = "../uv-cache" }
|
||||
uv-client = { path = "../uv-client" }
|
||||
|
@ -27,13 +27,13 @@ uv-installer = { path = "../uv-installer" }
|
|||
uv-interpreter = { path = "../uv-interpreter" }
|
||||
uv-resolver = { path = "../uv-resolver" }
|
||||
uv-traits = { path = "../uv-traits" }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
rustc-hash = { workspace = true }
|
||||
uv-virtualenv = { path = "../uv-virtualenv" }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
fs-err = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
rustc-hash = { workspace = true }
|
||||
tempfile = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
|
|
@ -22,6 +22,7 @@ pep440_rs = { path = "../pep440-rs", features = ["pubgrub"] }
|
|||
pep508_rs = { path = "../pep508-rs" }
|
||||
platform-host = { path = "../platform-host" }
|
||||
platform-tags = { path = "../platform-tags" }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
uv-cache = { path = "../uv-cache" }
|
||||
uv-client = { path = "../uv-client" }
|
||||
uv-distribution = { path = "../uv-distribution" }
|
||||
|
@ -30,7 +31,6 @@ uv-interpreter = { path = "../uv-interpreter" }
|
|||
uv-normalize = { path = "../uv-normalize" }
|
||||
uv-traits = { path = "../uv-traits" }
|
||||
uv-warnings = { path = "../uv-warnings" }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
|
||||
anstream = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
|
@ -62,7 +62,7 @@ url = { workspace = true }
|
|||
zip = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
gourgeist = { path = "../gourgeist" }
|
||||
uv-virtualenv = { path = "../uv-virtualenv" }
|
||||
uv-interpreter = { path = "../uv-interpreter" }
|
||||
|
||||
once_cell = { version = "1.19.0" }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "gourgeist"
|
||||
name = "uv-virtualenv"
|
||||
version = "0.0.4"
|
||||
publish = false
|
||||
description = "virtualenv creation implemented in rust"
|
||||
|
@ -14,7 +14,7 @@ authors = { workspace = true }
|
|||
license = { workspace = true }
|
||||
|
||||
[[bin]]
|
||||
name = "gourgeist"
|
||||
name = "uv-virtualenv"
|
||||
required-features = ["cli"]
|
||||
|
||||
[lints]
|
3
crates/uv-virtualenv/README.md
Normal file
3
crates/uv-virtualenv/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# uv-virtualenv
|
||||
|
||||
`uv-virtualenv` is a rust library to create Python virtual environments. It also has a CLI.
|
|
@ -11,10 +11,10 @@ use tracing_subscriber::layer::SubscriberExt;
|
|||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tracing_subscriber::{fmt, EnvFilter};
|
||||
|
||||
use gourgeist::{create_bare_venv, Prompt};
|
||||
use platform_host::Platform;
|
||||
use uv_cache::Cache;
|
||||
use uv_interpreter::{find_default_python, find_requested_python};
|
||||
use uv_virtualenv::{create_bare_venv, Prompt};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
struct Cli {
|
||||
|
@ -27,14 +27,14 @@ struct Cli {
|
|||
system_site_packages: bool,
|
||||
}
|
||||
|
||||
fn run() -> Result<(), gourgeist::Error> {
|
||||
fn run() -> Result<(), uv_virtualenv::Error> {
|
||||
let cli = Cli::parse();
|
||||
let location = cli.path.unwrap_or(Utf8PathBuf::from(".venv"));
|
||||
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())?
|
||||
} else {
|
||||
Cache::from_path(".gourgeist_cache")?
|
||||
Cache::from_path(".cache")?
|
||||
};
|
||||
let interpreter = if let Some(python_request) = &cli.python {
|
||||
find_requested_python(python_request, &platform, &cache)?.ok_or(
|
|
@ -16,12 +16,13 @@ workspace = true
|
|||
[dependencies]
|
||||
distribution-filename = { path = "../distribution-filename" }
|
||||
distribution-types = { path = "../distribution-types" }
|
||||
gourgeist = { path = "../gourgeist" }
|
||||
install-wheel-rs = { path = "../install-wheel-rs", features = ["clap"], default-features = false }
|
||||
pep440_rs = { path = "../pep440-rs" }
|
||||
pep508_rs = { path = "../pep508-rs" }
|
||||
platform-host = { path = "../platform-host" }
|
||||
platform-tags = { path = "../platform-tags" }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
requirements-txt = { path = "../requirements-txt" }
|
||||
uv-build = { path = "../uv-build" }
|
||||
uv-cache = { path = "../uv-cache", features = ["clap"] }
|
||||
uv-client = { path = "../uv-client" }
|
||||
|
@ -33,9 +34,8 @@ uv-interpreter = { path = "../uv-interpreter" }
|
|||
uv-normalize = { path = "../uv-normalize" }
|
||||
uv-resolver = { path = "../uv-resolver", features = ["clap"] }
|
||||
uv-traits = { path = "../uv-traits" }
|
||||
uv-virtualenv = { path = "../uv-virtualenv" }
|
||||
uv-warnings = { path = "../uv-warnings" }
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
requirements-txt = { path = "../requirements-txt" }
|
||||
|
||||
anstream = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
|
|
|
@ -12,7 +12,6 @@ use owo_colors::OwoColorize;
|
|||
use thiserror::Error;
|
||||
|
||||
use distribution_types::{DistributionMetadata, IndexLocations, Name};
|
||||
use gourgeist::Prompt;
|
||||
use pep508_rs::Requirement;
|
||||
use platform_host::Platform;
|
||||
use uv_cache::Cache;
|
||||
|
@ -33,7 +32,7 @@ pub(crate) async fn venv(
|
|||
path: &Path,
|
||||
python_request: Option<&str>,
|
||||
index_locations: &IndexLocations,
|
||||
prompt: Prompt,
|
||||
prompt: uv_virtualenv::Prompt,
|
||||
system_site_packages: bool,
|
||||
connectivity: Connectivity,
|
||||
seed: bool,
|
||||
|
@ -67,7 +66,7 @@ pub(crate) async fn venv(
|
|||
enum VenvError {
|
||||
#[error("Failed to create virtualenv")]
|
||||
#[diagnostic(code(uv::venv::creation))]
|
||||
Creation(#[source] gourgeist::Error),
|
||||
Creation(#[source] uv_virtualenv::Error),
|
||||
|
||||
#[error("Failed to install seed packages")]
|
||||
#[diagnostic(code(uv::venv::seed))]
|
||||
|
@ -88,7 +87,7 @@ async fn venv_impl(
|
|||
path: &Path,
|
||||
python_request: Option<&str>,
|
||||
index_locations: &IndexLocations,
|
||||
prompt: Prompt,
|
||||
prompt: uv_virtualenv::Prompt,
|
||||
system_site_packages: bool,
|
||||
connectivity: Connectivity,
|
||||
seed: bool,
|
||||
|
@ -126,8 +125,9 @@ async fn venv_impl(
|
|||
let extra_cfg = vec![("uv".to_string(), env!("CARGO_PKG_VERSION").to_string())];
|
||||
|
||||
// Create the virtual environment.
|
||||
let venv = gourgeist::create_venv(path, interpreter, prompt, system_site_packages, extra_cfg)
|
||||
.map_err(VenvError::Creation)?;
|
||||
let venv =
|
||||
uv_virtualenv::create_venv(path, interpreter, prompt, system_site_packages, extra_cfg)
|
||||
.map_err(VenvError::Creation)?;
|
||||
|
||||
// Install seed packages.
|
||||
if seed {
|
||||
|
|
|
@ -1397,7 +1397,7 @@ async fn run() -> Result<ExitStatus> {
|
|||
&args.name,
|
||||
args.python.as_deref(),
|
||||
&index_locations,
|
||||
gourgeist::Prompt::from_args(prompt),
|
||||
uv_virtualenv::Prompt::from_args(prompt),
|
||||
args.system_site_packages,
|
||||
if args.offline {
|
||||
Connectivity::Offline
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
exclude = [
|
||||
"crates/gourgeist/src/activator/activate_this.py",
|
||||
"crates/gourgeist/src/_virtualenv.py"
|
||||
"crates/uv-virtualenv/src/activator/activate_this.py",
|
||||
"crates/uv-virtualenv/src/_virtualenv.py"
|
||||
]
|
||||
[lint.per-file-ignores]
|
||||
"__init__.py" = ["F403", "F405"]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue