From e698de21a7d69bff7badea0fd1a2c1f65559eecb Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sat, 17 Jun 2023 11:38:35 +0200 Subject: [PATCH] Added --extra-requirement to rye install --- docs/guide/tools.md | 17 +++++++++++++ rye/src/cli/install.rs | 55 ++++++++++++++++++++++++++++++------------ rye/src/installer.rs | 5 ++++ 3 files changed, 61 insertions(+), 16 deletions(-) diff --git a/docs/guide/tools.md b/docs/guide/tools.md index dcb34318e3..421153630c 100644 --- a/docs/guide/tools.md +++ b/docs/guide/tools.md @@ -20,6 +20,23 @@ are placed in `~/.rye/shims`. The `install` command now considers custom sources configured in the `config.toml` file. For more information see [Dependency Sources](sources.md). +## Extra Requirements + +Some tools do not declare all of their dependencies since they might be optional. +In some cases these can be declared by passing extra features to the installer: + +```bash +rye install black --features colorama +``` + +If dependencies are not at all specified, then they can be provided with `--extra-requirement`. +This is particularly sometimes necessary if the tool uses `pkg_resources` (part of +`setuptools`) but forgets to declare that dependency: + +```bash +rye install gradio --extra-requirement setuptools +``` + ## Listing Tools If you want to see which tools are installed, you can use `rye tools list`: diff --git a/rye/src/cli/install.rs b/rye/src/cli/install.rs index 8cc43671f3..7d316ceb39 100644 --- a/rye/src/cli/install.rs +++ b/rye/src/cli/install.rs @@ -19,6 +19,9 @@ pub struct Args { /// Include scripts from a given dependency. #[arg(long)] include_dep: Vec, + /// Additional dependencies to install that are not declared by the main package. + #[arg(long)] + extra_requirement: Vec, /// Optionally the Python version to use. #[arg(short, long)] python: Option, @@ -35,27 +38,19 @@ pub struct Args { pub fn execute(mut cmd: Args) -> Result<(), Error> { let output = CommandOutput::from_quiet_and_verbose(cmd.quiet, cmd.verbose); + let mut extra_requirements = Vec::new(); - let mut requirement = match resolve_local_requirement(Path::new(&cmd.requirement), output)? { - Some(req) => req, - None => cmd.requirement.parse::().with_context(|| { - if cmd.requirement.contains("://") { - format!( - "failed to parse requirement '{}'. It looks like a URL, maybe \ - you wanted to use --url or --git", - cmd.requirement - ) - } else { - format!("failed to parse requirement '{}'", cmd.requirement) - } - })?, - }; - + // main requirement + let mut requirement = handle_requirement(&cmd.requirement, output, true)?; // installations here always use absolute paths for local references // because we do not have a rye workspace to work with. cmd.req_extras.force_absolute(); cmd.req_extras.apply_to_requirement(&mut requirement)?; + for req in cmd.extra_requirement { + extra_requirements.push(handle_requirement(&req, output, false)?); + } + let py_ver: PythonVersionRequest = match cmd.python { Some(ref py) => py.parse()?, None => PythonVersionRequest { @@ -67,6 +62,34 @@ pub fn execute(mut cmd: Args) -> Result<(), Error> { }, }; - install(requirement, &py_ver, cmd.force, &cmd.include_dep, output)?; + install( + requirement, + &py_ver, + cmd.force, + &cmd.include_dep, + &extra_requirements, + output, + )?; Ok(()) } + +fn handle_requirement( + req: &str, + output: CommandOutput, + local_hint: bool, +) -> Result { + Ok(match resolve_local_requirement(Path::new(req), output)? { + Some(req) => req, + None => req.parse::().with_context(|| { + if local_hint && req.contains("://") { + format!( + "failed to parse requirement '{}'. It looks like a URL, maybe \ + you wanted to use --url or --git", + req + ) + } else { + format!("failed to parse requirement '{}'", req) + } + })?, + }) +} diff --git a/rye/src/installer.rs b/rye/src/installer.rs index 80df903b27..93154e2373 100644 --- a/rye/src/installer.rs +++ b/rye/src/installer.rs @@ -71,6 +71,7 @@ pub fn install( py_ver: &PythonVersionRequest, force: bool, include_deps: &[String], + extra_requirements: &[Requirement], output: CommandOutput, ) -> Result<(), Error> { let config = Config::current(); @@ -121,6 +122,10 @@ pub fn install( cmd.arg("importlib-metadata==6.6.0"); } + for extra in extra_requirements { + cmd.arg(extra.to_string()); + } + let status = cmd.status()?; if !status.success() { uninstall_helper(&target_venv_path, &shim_dir)?;