mirror of https://github.com/astral-sh/uv
Read base requirements from `pyproject.toml` in `uv run` (#3101)
In addition to the requested requirements, we include requirements from a `pyproject.toml` file if it exists and install the current directory. Closes https://github.com/astral-sh/uv/issues/3104
This commit is contained in:
parent
becb12642a
commit
01a7b7a088
|
|
@ -8,7 +8,7 @@ use uv_warnings::warn_user;
|
||||||
|
|
||||||
use crate::confirm;
|
use crate::confirm;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum RequirementsSource {
|
pub enum RequirementsSource {
|
||||||
/// A package was provided on the command line (e.g., `pip install flask`).
|
/// A package was provided on the command line (e.g., `pip install flask`).
|
||||||
Package(String),
|
Package(String),
|
||||||
|
|
|
||||||
|
|
@ -1634,7 +1634,7 @@ pub(crate) struct RunArgs {
|
||||||
#[arg(allow_hyphen_values = true)]
|
#[arg(allow_hyphen_values = true)]
|
||||||
pub(crate) args: Vec<String>,
|
pub(crate) args: Vec<String>,
|
||||||
|
|
||||||
/// Always use a new virtual environment.
|
/// Always use a new virtual environment for execution.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub(crate) isolated: bool,
|
pub(crate) isolated: bool,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,15 +41,26 @@ use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
||||||
pub(crate) async fn run(
|
pub(crate) async fn run(
|
||||||
command: String,
|
command: String,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
requirements: &[RequirementsSource],
|
mut requirements: Vec<RequirementsSource>,
|
||||||
isolated: bool,
|
isolated: bool,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
|
// Copy the requirements into a set of overrides; we'll use this to prioritize
|
||||||
|
// requested requirements over those discovered in the project.
|
||||||
|
// We must retain these requirements as direct dependencies too, as overrides
|
||||||
|
// cannot be applied to transitive dependencies.
|
||||||
|
let overrides = requirements.clone();
|
||||||
|
|
||||||
|
// TODO(zanieb): Provide an opt-out for this behavior
|
||||||
|
if let Some(workspace_requirements) = find_workspace_requirements()? {
|
||||||
|
requirements.extend(workspace_requirements);
|
||||||
|
}
|
||||||
|
|
||||||
// Detect the current Python interpreter.
|
// Detect the current Python interpreter.
|
||||||
// TODO(zanieb): Create ephemeral environments
|
// TODO(zanieb): Create ephemeral environments
|
||||||
// TODO(zanieb): Accept `--python`
|
// TODO(zanieb): Accept `--python`
|
||||||
let run_env = environment_for_run(requirements, isolated, cache, printer).await?;
|
let run_env = environment_for_run(&requirements, &overrides, isolated, cache, printer).await?;
|
||||||
let python_env = run_env.python;
|
let python_env = run_env.python;
|
||||||
|
|
||||||
// Construct the command
|
// Construct the command
|
||||||
|
|
@ -98,12 +109,31 @@ struct RunEnvironment {
|
||||||
_temp_dir_drop: Option<TempDir>,
|
_temp_dir_drop: Option<TempDir>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn find_workspace_requirements() -> Result<Option<Vec<RequirementsSource>>> {
|
||||||
|
// TODO(zanieb): Add/use workspace logic to load requirements for a workspace
|
||||||
|
// We cannot use `Workspace::find` yet because it depends on a `[tool.uv]` section
|
||||||
|
let pyproject_path = std::env::current_dir()?.join("pyproject.toml");
|
||||||
|
if pyproject_path.exists() {
|
||||||
|
debug!(
|
||||||
|
"Loading requirements from {}",
|
||||||
|
pyproject_path.user_display()
|
||||||
|
);
|
||||||
|
return Ok(Some(vec![
|
||||||
|
RequirementsSource::from_requirements_file(pyproject_path),
|
||||||
|
RequirementsSource::from_package(".".to_string()),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns an environment for a `run` invocation.
|
/// Returns an environment for a `run` invocation.
|
||||||
///
|
///
|
||||||
/// Will use the current virtual environment (if any) unless `isolated` is true.
|
/// Will use the current virtual environment (if any) unless `isolated` is true.
|
||||||
/// Will create virtual environments in a temporary directory (if necessary).
|
/// Will create virtual environments in a temporary directory (if necessary).
|
||||||
async fn environment_for_run(
|
async fn environment_for_run(
|
||||||
requirements: &[RequirementsSource],
|
requirements: &[RequirementsSource],
|
||||||
|
overrides: &[RequirementsSource],
|
||||||
isolated: bool,
|
isolated: bool,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
|
|
@ -123,10 +153,16 @@ async fn environment_for_run(
|
||||||
let client_builder = BaseClientBuilder::default();
|
let client_builder = BaseClientBuilder::default();
|
||||||
|
|
||||||
// Read all requirements from the provided sources.
|
// Read all requirements from the provided sources.
|
||||||
// TODO(zanieb): Consider allowing overrides and constraints
|
// TODO(zanieb): Consider allowing constraints and extras
|
||||||
// TODO(zanieb): Allow specifying extras somehow
|
// TODO(zanieb): Allow specifying extras somehow
|
||||||
let spec =
|
let spec = RequirementsSpecification::from_sources(
|
||||||
RequirementsSpecification::from_simple_sources(requirements, &client_builder).await?;
|
requirements,
|
||||||
|
&[],
|
||||||
|
overrides,
|
||||||
|
&ExtrasSpecification::None,
|
||||||
|
&client_builder,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Check if the current environment satisfies the requirements
|
// Check if the current environment satisfies the requirements
|
||||||
if let Some(venv) = current_venv {
|
if let Some(venv) = current_venv {
|
||||||
|
|
|
||||||
|
|
@ -597,7 +597,7 @@ async fn run() -> Result<ExitStatus> {
|
||||||
commands::run(
|
commands::run(
|
||||||
args.command,
|
args.command,
|
||||||
args.args,
|
args.args,
|
||||||
&requirements,
|
requirements,
|
||||||
args.isolated,
|
args.isolated,
|
||||||
&cache,
|
&cache,
|
||||||
printer,
|
printer,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue