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;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RequirementsSource {
|
||||
/// A package was provided on the command line (e.g., `pip install flask`).
|
||||
Package(String),
|
||||
|
|
|
|||
|
|
@ -1634,7 +1634,7 @@ pub(crate) struct RunArgs {
|
|||
#[arg(allow_hyphen_values = true)]
|
||||
pub(crate) args: Vec<String>,
|
||||
|
||||
/// Always use a new virtual environment.
|
||||
/// Always use a new virtual environment for execution.
|
||||
#[arg(long)]
|
||||
pub(crate) isolated: bool,
|
||||
|
||||
|
|
|
|||
|
|
@ -41,15 +41,26 @@ use uv_types::{BuildIsolation, EmptyInstalledPackages, HashStrategy, InFlight};
|
|||
pub(crate) async fn run(
|
||||
command: String,
|
||||
args: Vec<String>,
|
||||
requirements: &[RequirementsSource],
|
||||
mut requirements: Vec<RequirementsSource>,
|
||||
isolated: bool,
|
||||
cache: &Cache,
|
||||
printer: Printer,
|
||||
) -> 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.
|
||||
// TODO(zanieb): Create ephemeral environments
|
||||
// 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;
|
||||
|
||||
// Construct the command
|
||||
|
|
@ -98,12 +109,31 @@ struct RunEnvironment {
|
|||
_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.
|
||||
///
|
||||
/// Will use the current virtual environment (if any) unless `isolated` is true.
|
||||
/// Will create virtual environments in a temporary directory (if necessary).
|
||||
async fn environment_for_run(
|
||||
requirements: &[RequirementsSource],
|
||||
overrides: &[RequirementsSource],
|
||||
isolated: bool,
|
||||
cache: &Cache,
|
||||
printer: Printer,
|
||||
|
|
@ -123,10 +153,16 @@ async fn environment_for_run(
|
|||
let client_builder = BaseClientBuilder::default();
|
||||
|
||||
// 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
|
||||
let spec =
|
||||
RequirementsSpecification::from_simple_sources(requirements, &client_builder).await?;
|
||||
let spec = RequirementsSpecification::from_sources(
|
||||
requirements,
|
||||
&[],
|
||||
overrides,
|
||||
&ExtrasSpecification::None,
|
||||
&client_builder,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Check if the current environment satisfies the requirements
|
||||
if let Some(venv) = current_venv {
|
||||
|
|
|
|||
|
|
@ -597,7 +597,7 @@ async fn run() -> Result<ExitStatus> {
|
|||
commands::run(
|
||||
args.command,
|
||||
args.args,
|
||||
&requirements,
|
||||
requirements,
|
||||
args.isolated,
|
||||
&cache,
|
||||
printer,
|
||||
|
|
|
|||
Loading…
Reference in New Issue