Add offline support to `uv tool run` and `uv run` (#3676)

Adds `--offline` support to `uv tool run` and `uv run` because I needed
it on the airplane today.

I think we should move `--offline` to the global settings like
`--native-tls`.
This commit is contained in:
Zanie Blue 2024-05-21 16:58:15 -04:00 committed by GitHub
parent e0b639828d
commit 84afca2696
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 62 additions and 7 deletions

View File

@ -850,9 +850,10 @@ impl MediaType {
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
pub enum Connectivity {
/// Allow access to the network.
#[default]
Online,
/// Do not allow access to the network.

View File

@ -1840,6 +1840,13 @@ pub(crate) struct RunArgs {
#[arg(long)]
pub(crate) with: Vec<String>,
/// Run offline, i.e., without accessing the network.
#[arg(global = true, long, overrides_with("no_offline"))]
pub(crate) offline: bool,
#[arg(long, overrides_with("offline"), hide = true)]
pub(crate) no_offline: bool,
/// The Python interpreter to use to build the run environment.
///
/// By default, `uv` uses the virtual environment in the current working directory or any parent
@ -1954,4 +1961,11 @@ pub(crate) struct ToolRunArgs {
group = "discovery"
)]
pub(crate) python: Option<String>,
/// Run offline, i.e., without accessing the network.
#[arg(global = true, long, overrides_with("no_offline"))]
pub(crate) offline: bool,
#[arg(long, overrides_with("offline"), hide = true)]
pub(crate) no_offline: bool,
}

View File

@ -11,7 +11,7 @@ use platform_tags::Tags;
use pypi_types::Yanked;
use tracing::debug;
use uv_cache::Cache;
use uv_client::{BaseClientBuilder, RegistryClient, RegistryClientBuilder};
use uv_client::{BaseClientBuilder, Connectivity, RegistryClient, RegistryClientBuilder};
use uv_configuration::{
Concurrency, ConfigSettings, Constraints, NoBinary, NoBuild, Overrides, PreviewMode, Reinstall,
SetupPyStrategy,
@ -468,11 +468,12 @@ pub(crate) async fn update_environment(
venv: PythonEnvironment,
requirements: &[RequirementsSource],
preview: PreviewMode,
connectivity: Connectivity,
cache: &Cache,
printer: Printer,
) -> Result<PythonEnvironment> {
// TODO(zanieb): Support client configuration
let client_builder = BaseClientBuilder::default();
let client_builder = BaseClientBuilder::default().connectivity(connectivity);
// Read all requirements from the provided sources.
// TODO(zanieb): Consider allowing constraints and extras
@ -524,6 +525,7 @@ pub(crate) async fn update_environment(
// Initialize the registry client.
// TODO(zanieb): Support client options e.g. offline, tls, etc.
let client = RegistryClientBuilder::new(cache.clone())
.connectivity(connectivity)
.markers(markers)
.platform(venv.interpreter().platform())
.build();

View File

@ -8,6 +8,7 @@ use tokio::process::Command;
use tracing::debug;
use uv_cache::Cache;
use uv_client::Connectivity;
use uv_configuration::PreviewMode;
use uv_interpreter::{PythonEnvironment, SystemPython};
use uv_requirements::{ProjectWorkspace, RequirementsSource};
@ -25,6 +26,7 @@ pub(crate) async fn run(
python: Option<String>,
isolated: bool,
preview: PreviewMode,
connectivity: Connectivity,
cache: &Cache,
printer: Printer,
) -> Result<ExitStatus> {
@ -60,8 +62,15 @@ pub(crate) async fn run(
// Install the project requirements.
Some(
project::update_environment(venv, &project.requirements(), preview, cache, printer)
.await?,
project::update_environment(
venv,
&project.requirements(),
preview,
connectivity,
cache,
printer,
)
.await?,
)
};
@ -101,7 +110,10 @@ pub(crate) async fn run(
)?;
// Install the ephemeral requirements.
Some(project::update_environment(venv, &requirements, preview, cache, printer).await?)
Some(
project::update_environment(venv, &requirements, preview, connectivity, cache, printer)
.await?,
)
};
// Construct the command

View File

@ -8,6 +8,7 @@ use tokio::process::Command;
use tracing::debug;
use uv_cache::Cache;
use uv_client::Connectivity;
use uv_configuration::PreviewMode;
use uv_interpreter::{PythonEnvironment, SystemPython};
use uv_requirements::RequirementsSource;
@ -25,6 +26,7 @@ pub(crate) async fn run(
python: Option<String>,
_isolated: bool,
preview: PreviewMode,
connectivity: Connectivity,
cache: &Cache,
printer: Printer,
) -> Result<ExitStatus> {
@ -65,7 +67,7 @@ pub(crate) async fn run(
// Install the ephemeral requirements.
let ephemeral_env =
Some(update_environment(venv, &requirements, preview, cache, printer).await?);
Some(update_environment(venv, &requirements, preview, connectivity, cache, printer).await?);
// TODO(zanieb): Determine the command via the package entry points
let command = target;

View File

@ -12,6 +12,7 @@ use owo_colors::OwoColorize;
use tracing::instrument;
use uv_cache::Cache;
use uv_client::Connectivity;
use uv_requirements::RequirementsSource;
use uv_workspace::Combine;
@ -565,6 +566,7 @@ async fn run() -> Result<ExitStatus> {
args.python,
globals.isolated,
globals.preview,
args.connectivity,
&cache,
printer,
)
@ -603,12 +605,18 @@ async fn run() -> Result<ExitStatus> {
Commands::Tool(ToolNamespace {
command: ToolCommand::Run(args),
}) => {
let connectivity = if args.offline {
Connectivity::Offline
} else {
Connectivity::Online
};
commands::run_tool(
args.target,
args.args,
args.python,
globals.isolated,
globals.preview,
connectivity,
&cache,
printer,
)

View File

@ -94,6 +94,10 @@ pub(crate) struct RunSettings {
pub(crate) args: Vec<OsString>,
pub(crate) with: Vec<String>,
pub(crate) python: Option<String>,
// Shared settings.
// TODO(zanieb): should be moved to a global setting
pub(crate) connectivity: Connectivity,
}
impl RunSettings {
@ -105,6 +109,8 @@ impl RunSettings {
args,
with,
python,
offline,
no_offline,
} = args;
Self {
@ -113,6 +119,16 @@ impl RunSettings {
args,
with,
python,
// Shared settings
connectivity: flag(offline, no_offline)
.map(|offline| {
if offline {
Connectivity::Offline
} else {
Connectivity::Online
}
})
.unwrap_or_default(),
}
}
}