From 2cdbd23864fd38f3db6f941da9842e2683b38d69 Mon Sep 17 00:00:00 2001 From: Haydn Evans Date: Fri, 13 Sep 2024 11:15:50 +0200 Subject: [PATCH] add ability to load from .env files before invoking the command --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + crates/uv-cli/src/lib.rs | 6 ++++++ crates/uv/Cargo.toml | 1 + crates/uv/src/commands/project/run.rs | 10 ++++++++++ crates/uv/src/lib.rs | 1 + crates/uv/src/settings.rs | 3 +++ docs/configuration/environment.md | 3 +++ docs/reference/cli.md | 5 +++++ 9 files changed, 37 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index f758e7141446..727594d0f30e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -944,6 +944,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "dunce" version = "1.0.5" @@ -4144,6 +4150,7 @@ dependencies = [ "byteorder", "clap", "ctrlc", + "dotenvy", "etcetera", "filetime", "flate2", diff --git a/Cargo.toml b/Cargo.toml index 67fc2a285d6f..e7a1a286d21e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,6 +92,7 @@ directories = { version = "5.0.1" } dirs-sys = { version = "0.4.1" } dunce = { version = "1.0.5" } either = { version = "1.13.0" } +dotenvy = { version = "0.15.7" } encoding_rs_io = { version = "0.1.7" } etcetera = { version = "0.8.0" } flate2 = { version = "1.0.33", default-features = false } diff --git a/crates/uv-cli/src/lib.rs b/crates/uv-cli/src/lib.rs index 80965752b394..c78054c43262 100644 --- a/crates/uv-cli/src/lib.rs +++ b/crates/uv-cli/src/lib.rs @@ -2660,6 +2660,12 @@ pub struct RunArgs { /// By default, environment modifications are omitted, but enabled under `--verbose`. #[arg(long, env = "UV_SHOW_RESOLUTION", value_parser = clap::builder::BoolishValueParser::new(), hide = true)] pub show_resolution: bool, + + /// Run the command and load environment variables from the `.env` file in the current project. + /// + /// By default, the .env file is not loaded. + #[arg(long, env = "UV_RUN_LOAD_DOTENV")] + pub load_dotenv: bool, } #[derive(Args)] diff --git a/crates/uv/Cargo.toml b/crates/uv/Cargo.toml index 788eff776abf..07cb9ba03fe9 100644 --- a/crates/uv/Cargo.toml +++ b/crates/uv/Cargo.toml @@ -59,6 +59,7 @@ axoupdater = { workspace = true, features = [ ], optional = true } clap = { workspace = true, features = ["derive", "string", "wrap_help"] } ctrlc = { workspace = true } +dotenvy = { workspace = true } flate2 = { workspace = true, default-features = false } fs-err = { workspace = true, features = ["tokio"] } futures = { workspace = true } diff --git a/crates/uv/src/commands/project/run.rs b/crates/uv/src/commands/project/run.rs index 635a0137ae6e..18d93e32e9d7 100644 --- a/crates/uv/src/commands/project/run.rs +++ b/crates/uv/src/commands/project/run.rs @@ -47,6 +47,7 @@ use crate::commands::reporters::PythonDownloadReporter; use crate::commands::{diagnostics, project, ExitStatus, SharedState}; use crate::printer::Printer; use crate::settings::ResolverInstallerSettings; +use dotenvy::dotenv_override; /// Run a command. #[allow(clippy::fn_params_excessive_bools)] @@ -68,6 +69,7 @@ pub(crate) async fn run( editable: EditableMode, python: Option, settings: ResolverInstallerSettings, + load_dotenv: bool, python_preference: PythonPreference, python_downloads: PythonDownloads, connectivity: Connectivity, @@ -823,6 +825,14 @@ pub(crate) async fn run( debug!("Running `{command}`"); let mut process = command.as_command(interpreter); + // Load the `.env` into the environment if the flag or ENV is set. + // This is done before setting the PATH or VIRTUAL_ENV environment variables + // to ensure they are not overwritten + if load_dotenv { + debug!("Loading `.env` file"); + dotenv_override().ok(); + }; + // Construct the `PATH` environment variable. let new_path = std::env::join_paths( ephemeral_env diff --git a/crates/uv/src/lib.rs b/crates/uv/src/lib.rs index 010538a0c007..53eaef83d2a3 100644 --- a/crates/uv/src/lib.rs +++ b/crates/uv/src/lib.rs @@ -1257,6 +1257,7 @@ async fn run_project( args.editable, args.python, args.settings, + args.load_dotenv, globals.python_preference, globals.python_downloads, globals.connectivity, diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index b9048eeef399..bad2ae0300e5 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -236,6 +236,7 @@ pub(crate) struct RunSettings { pub(crate) python: Option, pub(crate) refresh: Refresh, pub(crate) settings: ResolverInstallerSettings, + pub(crate) load_dotenv: bool, } impl RunSettings { @@ -267,6 +268,7 @@ impl RunSettings { no_project, python, show_resolution, + load_dotenv, } = args; Self { @@ -295,6 +297,7 @@ impl RunSettings { resolver_installer_options(installer, build), filesystem, ), + load_dotenv, } } } diff --git a/docs/configuration/environment.md b/docs/configuration/environment.md index cf29ad2913fa..d849b6584de0 100644 --- a/docs/configuration/environment.md +++ b/docs/configuration/environment.md @@ -75,6 +75,9 @@ uv accepts the following command-line arguments as environment variables: set, uv will use this password for publishing. - `UV_NO_SYNC`: Equivalent to the `--no-sync` command-line argument. If set, uv will skip updating the environment. +- `UV_RUN_LOAD_DOTENV`: Equivalent to the `--load-dotenv` command-line argument. If set, `uv run` + will load the .env file from the current project directory (if it exists) to load all ENVs into + the current process. In each case, the corresponding command-line argument takes precedence over an environment variable. diff --git a/docs/reference/cli.md b/docs/reference/cli.md index f4ce014ec43c..20b5112746c6 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -214,6 +214,11 @@ uv run [OPTIONS] [COMMAND]
  • symlink: Symbolically link packages from the wheel into the site-packages directory
  • +
    --load-dotenv

    Run the command and load environment variables from the .env file in the current project.

    + +

    By default, the .env file is not loaded.

    + +

    May also be set with the UV_RUN_LOAD_DOTENV environment variable.

    --locked

    Assert that the uv.lock will remain unchanged.

    Requires that the lockfile is up-to-date. If the lockfile is missing or needs to be updated, uv will exit with an error.