From 871782fe19435fb4ec7ed08c67b060da28295fb4 Mon Sep 17 00:00:00 2001 From: Kevin James Date: Sun, 6 Aug 2023 05:28:29 +0100 Subject: [PATCH] feat(install): add support for pre-injected packages (#900) --- CHANGELOG.md | 1 + src/pipx/commands/install.py | 6 ++++++ src/pipx/commands/reinstall.py | 1 + src/pipx/main.py | 9 +++++++++ src/pipx/venv.py | 4 ++-- 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e852abc717..a9eb9e3c38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Move `pipx` paths to ensure compatibility with the platform-specific user directories - [docs] Add more examples for `pipx run` - [docs] Add subsection to make README easier to read +- Add `pipx install --preinstall` to support preinstalling build requirements ## 1.2.0 diff --git a/src/pipx/commands/install.py b/src/pipx/commands/install.py index d10cd69feb..8d6ae2b94a 100644 --- a/src/pipx/commands/install.py +++ b/src/pipx/commands/install.py @@ -20,6 +20,7 @@ def install( *, force: bool, include_dependencies: bool, + preinstall_packages: Optional[List[str]], suffix: str = "", ) -> ExitCode: """Returns pipx exit code.""" @@ -58,6 +59,11 @@ def install( try: venv.create_venv(venv_args, pip_args) + for dep in preinstall_packages or []: + dep_name = package_name_from_spec( + dep, python, pip_args=pip_args, verbose=verbose + ) + venv.upgrade_package_no_metadata(dep_name, []) venv.install_package( package_name=package_name, package_or_url=package_spec, diff --git a/src/pipx/commands/reinstall.py b/src/pipx/commands/reinstall.py index 4271588c75..b8ab23fc97 100644 --- a/src/pipx/commands/reinstall.py +++ b/src/pipx/commands/reinstall.py @@ -70,6 +70,7 @@ def reinstall( verbose, force=True, include_dependencies=venv.pipx_metadata.main_package.include_dependencies, + preinstall_packages=[], suffix=venv.pipx_metadata.main_package.suffix, ) diff --git a/src/pipx/main.py b/src/pipx/main.py index 5629e3adce..7f12fba23b 100644 --- a/src/pipx/main.py +++ b/src/pipx/main.py @@ -213,6 +213,7 @@ def run_pipx_command(args: argparse.Namespace) -> ExitCode: # noqa: C901 verbose, force=args.force, include_dependencies=args.include_deps, + preinstall_packages=args.preinstall, suffix=args.suffix, ) elif args.command == "inject": @@ -350,6 +351,14 @@ def _add_install(subparsers: argparse._SubParsersAction) -> None: f"Requires Python {MINIMUM_PYTHON_VERSION} or above." ), ) + p.add_argument( + "--preinstall", + action="append", + help=( + "Optional packages to be installed into the Virtual Environment before " + "installing the main package." + ), + ) add_pip_venv_args(p) diff --git a/src/pipx/venv.py b/src/pipx/venv.py index b6d01ce490..5714341579 100644 --- a/src/pipx/venv.py +++ b/src/pipx/venv.py @@ -201,7 +201,7 @@ def upgrade_packaging_libraries(self, pip_args: List[str]) -> None: else: # TODO: setuptools and wheel? Original code didn't bother # but shared libs code does. - self._upgrade_package_no_metadata("pip", pip_args) + self.upgrade_package_no_metadata("pip", pip_args) def uninstall_package(self, package: str, was_injected: bool = False): try: @@ -421,7 +421,7 @@ def has_app(self, app: str, filename: str) -> bool: return True return (self.bin_path / filename).is_file() - def _upgrade_package_no_metadata( + def upgrade_package_no_metadata( self, package_name: str, pip_args: List[str] ) -> None: with animate(