Skip to content

Commit

Permalink
Add uv sync --script
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Feb 9, 2025
1 parent 8e6f8ed commit 9626138
Show file tree
Hide file tree
Showing 7 changed files with 462 additions and 146 deletions.
14 changes: 14 additions & 0 deletions crates/uv-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3135,6 +3135,20 @@ pub struct SyncArgs {
#[arg(long, conflicts_with = "all_packages")]
pub package: Option<PackageName>,

/// Sync the virtual environment for the specified PEP 723 Python script, rather than the current
/// project.
///
/// If provided, uv will sync the dependencies based on the script's inline metadata table, in
/// adherence with PEP 723.
#[arg(
long,
conflicts_with = "all_packages",
conflicts_with = "package",
conflicts_with = "no_install_project",
conflicts_with = "no_install_workspace"
)]
pub script: Option<PathBuf>,

/// The Python interpreter to use for the project environment.
///
/// By default, the first interpreter that meets the project's `requires-python` constraint is
Expand Down
48 changes: 41 additions & 7 deletions crates/uv/src/commands/project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1155,9 +1155,23 @@ impl ProjectEnvironment {
}
}

/// The Python environment for a project.
/// The Python environment for a script.
#[derive(Debug)]
struct ScriptEnvironment(PythonEnvironment);
enum ScriptEnvironment {
/// An existing [`PythonEnvironment`] was discovered, which satisfies the script's requirements.
Existing(PythonEnvironment),
/// An existing [`PythonEnvironment`] was discovered, but did not satisfy the script's
/// requirements, and so was replaced.
///
/// In `--dry-run` mode, the environment will not be replaced, but this variant will still be
/// returned.
Replaced(PythonEnvironment, PathBuf),
/// A new [`PythonEnvironment`] was created.
///
/// In `--dry-run` mode, the environment will not be created, but this variant will still be
/// returned.
New(PythonEnvironment, PathBuf),
}

impl ScriptEnvironment {
/// Initialize a virtual environment for a PEP 723 script.
Expand All @@ -1172,6 +1186,7 @@ impl ScriptEnvironment {
install_mirrors: &PythonInstallMirrors,
no_config: bool,
cache: &Cache,
dry_run: DryRun,
printer: Printer,
) -> Result<Self, ProjectError> {
// Lock the script environment to avoid synchronization issues.
Expand All @@ -1193,23 +1208,34 @@ impl ScriptEnvironment {
.await?
{
// If we found an existing, compatible environment, use it.
ScriptInterpreter::Environment(environment) => Ok(Self(environment)),
ScriptInterpreter::Environment(environment) => Ok(Self::Existing(environment)),

// Otherwise, create a virtual environment with the discovered interpreter.
ScriptInterpreter::Interpreter(interpreter) => {
let root = cache
.shard(CacheBucket::Environments, cache_digest(&script.path))
.into_path_buf();

// Under `--dry-run`, avoid modifying the environment.
if dry_run.enabled() {
let environment = PythonEnvironment::from_interpreter(interpreter);
return Ok(if root.exists() {
Self::Replaced(environment, root)
} else {
Self::New(environment, root)
});
}

// Remove the existing virtual environment.
match fs_err::remove_dir_all(&root) {
let replaced = match fs_err::remove_dir_all(&root) {
Ok(()) => {
debug!(
"Removed virtual environment at: {}",
root.user_display().cyan()
);
true
}
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {}
Err(err) if err.kind() == std::io::ErrorKind::NotFound => false,
Err(err) => return Err(err.into()),
};

Expand Down Expand Up @@ -1239,14 +1265,22 @@ impl ScriptEnvironment {
false,
)?;

Ok(Self(environment))
Ok(if replaced {
Self::Replaced(environment, root)
} else {
Self::New(environment, root)
})
}
}
}

/// Convert the [`ScriptEnvironment`] into a [`PythonEnvironment`].
pub(crate) fn into_environment(self) -> PythonEnvironment {
self.0
match self {
Self::Existing(environment) => environment,
Self::Replaced(environment, ..) => environment,
Self::New(environment, ..) => environment,
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions crates/uv/src/commands/project/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ pub(crate) async fn run(
&install_mirrors,
no_config,
cache,
DryRun::Disabled,
printer,
)
.await?
Expand Down Expand Up @@ -422,6 +423,7 @@ pub(crate) async fn run(
&install_mirrors,
no_config,
cache,
DryRun::Disabled,
printer,
)
.await?
Expand Down
Loading

0 comments on commit 9626138

Please sign in to comment.