Support --active for PEP 723 script environments (#11433)
## Summary See: https://github.com/astral-sh/uv/pull/11361#discussion_r1948851085
This commit is contained in:
Generated
+1
-1
@@ -5111,6 +5111,7 @@ dependencies = [
|
||||
"path-slash",
|
||||
"percent-encoding",
|
||||
"rustix",
|
||||
"same-file",
|
||||
"schemars",
|
||||
"serde",
|
||||
"tempfile",
|
||||
@@ -5789,7 +5790,6 @@ dependencies = [
|
||||
"owo-colors",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"same-file",
|
||||
"schemars",
|
||||
"serde",
|
||||
"tempfile",
|
||||
|
||||
@@ -3053,10 +3053,11 @@ pub struct SyncArgs {
|
||||
#[arg(long, overrides_with("inexact"), hide = true)]
|
||||
pub exact: bool,
|
||||
|
||||
/// Prefer the active virtual environment over the project's virtual environment.
|
||||
/// Sync dependencies to the active virtual environment.
|
||||
///
|
||||
/// If the project virtual environment is active or no virtual environment is active, this has
|
||||
/// no effect.
|
||||
/// Instead of creating or updating the virtual environment for the project or script, the
|
||||
/// active virtual environment will be preferred, if the `VIRTUAL_ENV` environment variable is
|
||||
/// set.
|
||||
#[arg(long, overrides_with = "no_active")]
|
||||
pub active: bool,
|
||||
|
||||
@@ -3150,7 +3151,6 @@ pub struct SyncArgs {
|
||||
/// adherence with PEP 723.
|
||||
#[arg(
|
||||
long,
|
||||
conflicts_with = "active",
|
||||
conflicts_with = "all_packages",
|
||||
conflicts_with = "package",
|
||||
conflicts_with = "no_install_project",
|
||||
|
||||
@@ -23,6 +23,7 @@ fs-err = { workspace = true }
|
||||
fs2 = { workspace = true }
|
||||
path-slash = { workspace = true }
|
||||
percent-encoding = { workspace = true }
|
||||
same-file = { workspace = true }
|
||||
schemars = { workspace = true, optional = true }
|
||||
serde = { workspace = true, optional = true }
|
||||
tempfile = { workspace = true }
|
||||
|
||||
@@ -11,6 +11,38 @@ pub mod cachedir;
|
||||
mod path;
|
||||
pub mod which;
|
||||
|
||||
/// Attempt to check if the two paths refer to the same file.
|
||||
///
|
||||
/// Returns `Some(true)` if the files are missing, but would be the same if they existed.
|
||||
pub fn is_same_file_allow_missing(left: &Path, right: &Path) -> Option<bool> {
|
||||
// First, check an exact path comparison.
|
||||
if left == right {
|
||||
return Some(true);
|
||||
}
|
||||
|
||||
// Second, check the files directly.
|
||||
if let Ok(value) = same_file::is_same_file(left, right) {
|
||||
return Some(value);
|
||||
};
|
||||
|
||||
// Often, one of the directories won't exist yet so perform the comparison up a level.
|
||||
if let (Some(left_parent), Some(right_parent), Some(left_name), Some(right_name)) = (
|
||||
left.parent(),
|
||||
right.parent(),
|
||||
left.file_name(),
|
||||
right.file_name(),
|
||||
) {
|
||||
match same_file::is_same_file(left_parent, right_parent) {
|
||||
Ok(true) => return Some(left_name == right_name),
|
||||
Ok(false) => return Some(false),
|
||||
_ => (),
|
||||
}
|
||||
};
|
||||
|
||||
// We couldn't determine if they're the same.
|
||||
None
|
||||
}
|
||||
|
||||
/// Reads data from the path and requires that it be valid UTF-8 or UTF-16.
|
||||
///
|
||||
/// This uses BOM sniffing to determine if the data should be transcoded
|
||||
|
||||
@@ -34,7 +34,6 @@ glob = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
owo-colors = { workspace = true }
|
||||
rustc-hash = { workspace = true }
|
||||
same-file = { workspace = true }
|
||||
schemars = { workspace = true, optional = true }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
@@ -560,7 +560,7 @@ impl Workspace {
|
||||
Some(workspace.install_path.join(path))
|
||||
}
|
||||
|
||||
// Resolve the `VIRTUAL_ENV` variable, if any.
|
||||
/// Resolve the `VIRTUAL_ENV` variable, if any.
|
||||
fn from_virtual_env_variable() -> Option<PathBuf> {
|
||||
let value = std::env::var_os(EnvVars::VIRTUAL_ENV)?;
|
||||
|
||||
@@ -578,38 +578,14 @@ impl Workspace {
|
||||
Some(CWD.join(path))
|
||||
}
|
||||
|
||||
// Attempt to check if the two paths refer to the same directory.
|
||||
fn is_same_dir(left: &Path, right: &Path) -> Option<bool> {
|
||||
// First, attempt to check directly
|
||||
if let Ok(value) = same_file::is_same_file(left, right) {
|
||||
return Some(value);
|
||||
};
|
||||
|
||||
// Often, one of the directories won't exist yet so perform the comparison up a level
|
||||
if let (Some(left_parent), Some(right_parent), Some(left_name), Some(right_name)) = (
|
||||
left.parent(),
|
||||
right.parent(),
|
||||
left.file_name(),
|
||||
right.file_name(),
|
||||
) {
|
||||
match same_file::is_same_file(left_parent, right_parent) {
|
||||
Ok(true) => return Some(left_name == right_name),
|
||||
Ok(false) => return Some(false),
|
||||
_ => (),
|
||||
}
|
||||
};
|
||||
|
||||
// We couldn't determine if they're the same
|
||||
None
|
||||
}
|
||||
|
||||
// Determine the default value
|
||||
let project_env = from_project_environment_variable(self)
|
||||
.unwrap_or_else(|| self.install_path.join(".venv"));
|
||||
|
||||
// Warn if it conflicts with `VIRTUAL_ENV`
|
||||
if let Some(from_virtual_env) = from_virtual_env_variable() {
|
||||
if !is_same_dir(&from_virtual_env, &project_env).unwrap_or(false) {
|
||||
if !uv_fs::is_same_file_allow_missing(&from_virtual_env, &project_env).unwrap_or(false)
|
||||
{
|
||||
match active {
|
||||
Some(true) => {
|
||||
debug!(
|
||||
|
||||
@@ -165,6 +165,7 @@ pub(crate) async fn add(
|
||||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
active,
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
|
||||
@@ -147,6 +147,7 @@ pub(crate) async fn export(
|
||||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
Some(false),
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
|
||||
@@ -137,6 +137,7 @@ pub(crate) async fn lock(
|
||||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
Some(false),
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
|
||||
@@ -40,6 +40,7 @@ use uv_resolver::{
|
||||
};
|
||||
use uv_scripts::Pep723ItemRef;
|
||||
use uv_settings::PythonInstallMirrors;
|
||||
use uv_static::EnvVars;
|
||||
use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy};
|
||||
use uv_warnings::{warn_user, warn_user_once};
|
||||
use uv_workspace::dependency_groups::DependencyGroupError;
|
||||
@@ -532,30 +533,88 @@ pub(crate) enum ScriptInterpreter {
|
||||
|
||||
impl ScriptInterpreter {
|
||||
/// Return the expected virtual environment path for the [`Pep723Script`].
|
||||
pub(crate) fn root(script: Pep723ItemRef<'_>, cache: &Cache) -> PathBuf {
|
||||
let entry = match script {
|
||||
// For local scripts, use a hash of the path to the script.
|
||||
Pep723ItemRef::Script(script) => {
|
||||
let digest = cache_digest(&script.path);
|
||||
if let Some(file_name) = script
|
||||
.path
|
||||
.file_stem()
|
||||
.and_then(|name| name.to_str())
|
||||
.and_then(cache_name)
|
||||
{
|
||||
format!("{file_name}-{digest}")
|
||||
} else {
|
||||
digest
|
||||
///
|
||||
/// If `--active` is set, the active virtual environment will be preferred.
|
||||
///
|
||||
/// See: [`Workspace::venv`].
|
||||
pub(crate) fn root(script: Pep723ItemRef<'_>, active: Option<bool>, cache: &Cache) -> PathBuf {
|
||||
/// Resolve the `VIRTUAL_ENV` variable, if any.
|
||||
fn from_virtual_env_variable() -> Option<PathBuf> {
|
||||
let value = std::env::var_os(EnvVars::VIRTUAL_ENV)?;
|
||||
|
||||
if value.is_empty() {
|
||||
return None;
|
||||
};
|
||||
|
||||
let path = PathBuf::from(value);
|
||||
if path.is_absolute() {
|
||||
return Some(path);
|
||||
};
|
||||
|
||||
// Resolve the path relative to current directory.
|
||||
Some(CWD.join(path))
|
||||
}
|
||||
|
||||
// Determine the stable path to the script environment in the cache.
|
||||
let cache_env = {
|
||||
let entry = match script {
|
||||
// For local scripts, use a hash of the path to the script.
|
||||
Pep723ItemRef::Script(script) => {
|
||||
let digest = cache_digest(&script.path);
|
||||
if let Some(file_name) = script
|
||||
.path
|
||||
.file_stem()
|
||||
.and_then(|name| name.to_str())
|
||||
.and_then(cache_name)
|
||||
{
|
||||
format!("{file_name}-{digest}")
|
||||
} else {
|
||||
digest
|
||||
}
|
||||
}
|
||||
// For remote scripts, use a hash of the URL.
|
||||
Pep723ItemRef::Remote(.., url) => cache_digest(url),
|
||||
// Otherwise, use a hash of the metadata.
|
||||
Pep723ItemRef::Stdin(metadata) => cache_digest(&metadata.raw),
|
||||
};
|
||||
|
||||
cache
|
||||
.shard(CacheBucket::Environments, entry)
|
||||
.into_path_buf()
|
||||
};
|
||||
|
||||
// If `--active` is set, prefer the active virtual environment.
|
||||
if let Some(from_virtual_env) = from_virtual_env_variable() {
|
||||
if !uv_fs::is_same_file_allow_missing(&from_virtual_env, &cache_env).unwrap_or(false) {
|
||||
match active {
|
||||
Some(true) => {
|
||||
debug!(
|
||||
"Using active virtual environment `{}` instead of script environment `{}`",
|
||||
from_virtual_env.user_display(),
|
||||
cache_env.user_display()
|
||||
);
|
||||
return from_virtual_env;
|
||||
}
|
||||
Some(false) => {}
|
||||
None => {
|
||||
warn_user_once!(
|
||||
"`VIRTUAL_ENV={}` does not match the script environment path `{}` and will be ignored; use `--active` to target the active environment instead",
|
||||
from_virtual_env.user_display(),
|
||||
cache_env.user_display()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// For remote scripts, use a hash of the URL.
|
||||
Pep723ItemRef::Remote(.., url) => cache_digest(url),
|
||||
// Otherwise, use a hash of the metadata.
|
||||
Pep723ItemRef::Stdin(metadata) => cache_digest(&metadata.raw),
|
||||
};
|
||||
cache
|
||||
.shard(CacheBucket::Environments, entry)
|
||||
.into_path_buf()
|
||||
} else {
|
||||
if active.unwrap_or_default() {
|
||||
debug!(
|
||||
"Use of the active virtual environment was requested, but `VIRTUAL_ENV` is not set"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, use the cache root.
|
||||
cache_env
|
||||
}
|
||||
|
||||
/// Discover the interpreter to use for the current [`Pep723Item`].
|
||||
@@ -569,6 +628,7 @@ impl ScriptInterpreter {
|
||||
allow_insecure_host: &[TrustedHost],
|
||||
install_mirrors: &PythonInstallMirrors,
|
||||
no_config: bool,
|
||||
active: Option<bool>,
|
||||
cache: &Cache,
|
||||
printer: Printer,
|
||||
) -> Result<Self, ProjectError> {
|
||||
@@ -581,7 +641,8 @@ impl ScriptInterpreter {
|
||||
requires_python,
|
||||
} = ScriptPython::from_request(python_request, workspace, script, no_config).await?;
|
||||
|
||||
let root = Self::root(script, cache);
|
||||
let root = Self::root(script, active, cache);
|
||||
|
||||
match PythonEnvironment::from_root(&root, cache) {
|
||||
Ok(venv) => {
|
||||
if python_request.as_ref().map_or(true, |request| {
|
||||
@@ -1279,6 +1340,7 @@ impl ScriptEnvironment {
|
||||
allow_insecure_host: &[TrustedHost],
|
||||
install_mirrors: &PythonInstallMirrors,
|
||||
no_config: bool,
|
||||
active: Option<bool>,
|
||||
cache: &Cache,
|
||||
dry_run: DryRun,
|
||||
printer: Printer,
|
||||
@@ -1296,6 +1358,7 @@ impl ScriptEnvironment {
|
||||
allow_insecure_host,
|
||||
install_mirrors,
|
||||
no_config,
|
||||
active,
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
@@ -1306,7 +1369,7 @@ impl ScriptEnvironment {
|
||||
|
||||
// Otherwise, create a virtual environment with the discovered interpreter.
|
||||
ScriptInterpreter::Interpreter(interpreter) => {
|
||||
let root = ScriptInterpreter::root(script, cache);
|
||||
let root = ScriptInterpreter::root(script, active, cache);
|
||||
|
||||
// Determine a prompt for the environment, in order of preference:
|
||||
//
|
||||
|
||||
@@ -253,6 +253,7 @@ pub(crate) async fn remove(
|
||||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
active,
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
|
||||
@@ -226,6 +226,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
active.map_or(Some(false), Some),
|
||||
cache,
|
||||
DryRun::Disabled,
|
||||
printer,
|
||||
@@ -346,6 +347,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
active.map_or(Some(false), Some),
|
||||
cache,
|
||||
DryRun::Disabled,
|
||||
printer,
|
||||
@@ -402,6 +404,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl
|
||||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
active.map_or(Some(false), Some),
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
|
||||
@@ -172,6 +172,7 @@ pub(crate) async fn sync(
|
||||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
active,
|
||||
cache,
|
||||
dry_run,
|
||||
printer,
|
||||
|
||||
@@ -102,6 +102,7 @@ pub(crate) async fn tree(
|
||||
allow_insecure_host,
|
||||
&install_mirrors,
|
||||
no_config,
|
||||
Some(false),
|
||||
cache,
|
||||
printer,
|
||||
)
|
||||
|
||||
+110
-1
@@ -3514,7 +3514,7 @@ fn run_linked_environment_path() -> Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_active_environment() -> Result<()> {
|
||||
fn run_active_project_environment() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&["3.11", "3.12"])
|
||||
.with_filtered_virtualenv_bin()
|
||||
.with_filtered_python_names();
|
||||
@@ -3620,6 +3620,115 @@ fn run_active_environment() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_active_script_environment() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&["3.11", "3.12"])
|
||||
.with_filtered_virtualenv_bin()
|
||||
.with_filtered_python_names();
|
||||
|
||||
let test_script = context.temp_dir.child("main.py");
|
||||
test_script.write_str(indoc! { r#"
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# dependencies = [
|
||||
# "iniconfig",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
import iniconfig
|
||||
|
||||
print("Hello, world!")
|
||||
"#
|
||||
})?;
|
||||
|
||||
let filters = context
|
||||
.filters()
|
||||
.into_iter()
|
||||
.chain(vec![(
|
||||
r"environments-v1/main-\w+",
|
||||
"environments-v1/main-[HASH]",
|
||||
)])
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Running `uv run --script` with `VIRTUAL_ENV` should _not_ warn.
|
||||
uv_snapshot!(&filters, context.run()
|
||||
.arg("--script")
|
||||
.arg("main.py")
|
||||
.env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Hello, world!
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Prepared 1 package in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
+ iniconfig==2.0.0
|
||||
"###);
|
||||
|
||||
// Using `--no-active` should also _not_ warn.
|
||||
uv_snapshot!(&filters, context.run()
|
||||
.arg("--no-active")
|
||||
.arg("--script")
|
||||
.arg("main.py")
|
||||
.env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Hello, world!
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
|
||||
context
|
||||
.temp_dir
|
||||
.child("foo")
|
||||
.assert(predicate::path::missing());
|
||||
|
||||
// Using `--active` should create the environment
|
||||
uv_snapshot!(&filters, context.run()
|
||||
.arg("--active")
|
||||
.arg("--script")
|
||||
.arg("main.py")
|
||||
.env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Hello, world!
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
+ iniconfig==2.0.0
|
||||
"###);
|
||||
|
||||
context
|
||||
.temp_dir
|
||||
.child("foo")
|
||||
.assert(predicate::path::is_dir());
|
||||
|
||||
// Requesting a different Python version should invalidate the environment
|
||||
uv_snapshot!(&filters, context.run()
|
||||
.arg("--active")
|
||||
.arg("-p").arg("3.12")
|
||||
.arg("--script")
|
||||
.arg("main.py")
|
||||
.env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Hello, world!
|
||||
|
||||
----- stderr -----
|
||||
Resolved 1 package in [TIME]
|
||||
Installed 1 package in [TIME]
|
||||
+ iniconfig==2.0.0
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn run_gui_script_explicit_stdin_unix() -> Result<()> {
|
||||
|
||||
+105
-1
@@ -3400,7 +3400,7 @@ fn sync_custom_environment_path() -> Result<()> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_active_environment() -> Result<()> {
|
||||
fn sync_active_project_environment() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&["3.11", "3.12"])
|
||||
.with_filtered_virtualenv_bin()
|
||||
.with_filtered_python_names();
|
||||
@@ -3524,6 +3524,110 @@ fn sync_active_environment() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_active_script_environment() -> Result<()> {
|
||||
let context = TestContext::new_with_versions(&["3.11", "3.12"])
|
||||
.with_filtered_virtualenv_bin()
|
||||
.with_filtered_python_names();
|
||||
|
||||
let script = context.temp_dir.child("script.py");
|
||||
script.write_str(indoc! { r#"
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# dependencies = [
|
||||
# "anyio",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
import anyio
|
||||
"#
|
||||
})?;
|
||||
|
||||
let filters = context
|
||||
.filters()
|
||||
.into_iter()
|
||||
.chain(vec![(
|
||||
r"environments-v1/script-\w+",
|
||||
"environments-v1/script-[HASH]",
|
||||
)])
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Running `uv sync --script` with `VIRTUAL_ENV` should warn
|
||||
uv_snapshot!(&filters, context.sync().arg("--script").arg("script.py").env(EnvVars::VIRTUAL_ENV, "foo"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
warning: `VIRTUAL_ENV=foo` does not match the script environment path `[CACHE_DIR]/environments-v1/script-[HASH]` and will be ignored; use `--active` to target the active environment instead
|
||||
Creating script environment at: [CACHE_DIR]/environments-v1/script-[HASH]
|
||||
Resolved 3 packages in [TIME]
|
||||
Prepared 3 packages in [TIME]
|
||||
Installed 3 packages in [TIME]
|
||||
+ anyio==4.3.0
|
||||
+ idna==3.6
|
||||
+ sniffio==1.3.1
|
||||
"###);
|
||||
|
||||
context
|
||||
.temp_dir
|
||||
.child("foo")
|
||||
.assert(predicate::path::missing());
|
||||
|
||||
// Using `--active` should create the environment
|
||||
uv_snapshot!(&filters, context.sync().arg("--script").arg("script.py").env(EnvVars::VIRTUAL_ENV, "foo").arg("--active"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Creating script environment at: foo
|
||||
Resolved 3 packages in [TIME]
|
||||
Installed 3 packages in [TIME]
|
||||
+ anyio==4.3.0
|
||||
+ idna==3.6
|
||||
+ sniffio==1.3.1
|
||||
"###);
|
||||
|
||||
context
|
||||
.temp_dir
|
||||
.child("foo")
|
||||
.assert(predicate::path::is_dir());
|
||||
|
||||
// A subsequent sync will re-use the environment
|
||||
uv_snapshot!(&filters, context.sync().arg("--script").arg("script.py").env(EnvVars::VIRTUAL_ENV, "foo").arg("--active"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Using script environment at: foo
|
||||
"###);
|
||||
|
||||
// Requesting another Python version will invalidate the environment
|
||||
uv_snapshot!(&filters, context.sync()
|
||||
.arg("--script")
|
||||
.arg("script.py")
|
||||
.env(EnvVars::VIRTUAL_ENV, "foo")
|
||||
.arg("--active")
|
||||
.arg("-p")
|
||||
.arg("3.12"), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Recreating script environment at: foo
|
||||
Resolved 3 packages in [TIME]
|
||||
Installed 3 packages in [TIME]
|
||||
+ anyio==4.3.0
|
||||
+ idna==3.6
|
||||
+ sniffio==1.3.1
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "git")]
|
||||
fn sync_workspace_custom_environment_path() -> Result<()> {
|
||||
|
||||
@@ -1486,9 +1486,9 @@ uv sync [OPTIONS]
|
||||
|
||||
<h3 class="cli-reference">Options</h3>
|
||||
|
||||
<dl class="cli-reference"><dt><code>--active</code></dt><dd><p>Prefer the active virtual environment over the project’s virtual environment.</p>
|
||||
<dl class="cli-reference"><dt><code>--active</code></dt><dd><p>Sync dependencies to the active virtual environment.</p>
|
||||
|
||||
<p>If the project virtual environment is active or no virtual environment is active, this has no effect.</p>
|
||||
<p>Instead of creating or updating the virtual environment for the project or script, the active virtual environment will be preferred, if the <code>VIRTUAL_ENV</code> environment variable is set.</p>
|
||||
|
||||
</dd><dt><code>--all-extras</code></dt><dd><p>Include all optional dependencies.</p>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user