Skip to content

Commit

Permalink
Separate list depeendencies to a separate installer class
Browse files Browse the repository at this point in the history
This allows other installers (such as uv) to reuse this code.

Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
  • Loading branch information
gaborbernat committed Sep 19, 2024
1 parent 0cb816c commit 434479f
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 17 deletions.
2 changes: 2 additions & 0 deletions docs/changelog/3347.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Separate the list dependencies functionality to a separate abstract class allowing code reuse in plugins (such as
``tox-uv``) - by :gaborbernat`.
50 changes: 33 additions & 17 deletions src/tox/tox_env/python/pip/pip_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import logging
import operator
from abc import ABC, abstractmethod
from collections import defaultdict
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable, Sequence
Expand All @@ -21,14 +22,36 @@
from tox.tox_env.package import PathPackage


class Pip(Installer[Python]):
"""Pip is a python installer that can install packages as defined by PEP-508 and PEP-517."""

class PythonInstallerList(Installer[Python], ABC):
def __init__(self, tox_env: Python, with_list_deps: bool = True) -> None: # noqa: FBT001, FBT002
self._with_list_deps = with_list_deps
super().__init__(tox_env)

def _register_config(self) -> None:
if self._with_list_deps: # pragma: no branch
self._env.conf.add_config(
keys=["list_dependencies_command"],
of_type=Command,
default=Command(self.freeze_cmd()),
desc="command used to list installed packages",
)

@abstractmethod
def freeze_cmd(self) -> list[str]:
raise NotImplementedError

def installed(self) -> list[str]:
cmd: Command = self._env.conf["list_dependencies_command"]
result = self._env.execute(cmd=cmd.args, stdin=StdinSource.OFF, run_id="freeze", show=False)
result.assert_success()
return result.out.splitlines()


class Pip(PythonInstallerList):
"""Pip is a python installer that can install packages as defined by PEP-508 and PEP-517."""

def _register_config(self) -> None:
super()._register_config()
self._env.conf.add_config(
keys=["pip_pre"],
of_type=bool,
Expand All @@ -54,13 +77,9 @@ def _register_config(self) -> None:
default=False,
desc="Use the exact versions of installed deps as constraints, otherwise use the listed deps.",
)
if self._with_list_deps: # pragma: no branch
self._env.conf.add_config(
keys=["list_dependencies_command"],
of_type=Command,
default=Command(["python", "-m", "pip", "freeze", "--all"]),
desc="command used to list installed packages",
)

def freeze_cmd(self) -> list[str]: # noqa: PLR6301
return ["python", "-m", "pip", "freeze", "--all"]

def default_install_command(self, conf: Config, env_name: str | None) -> Command: # noqa: ARG002
isolated_flag = "-E" if self._env.base_python.version_info.major == 2 else "-I" # noqa: PLR2004
Expand All @@ -82,12 +101,6 @@ def post_process_install_command(self, cmd: Command) -> Command:
install_command.pop(opts_at)
return cmd

def installed(self) -> list[str]:
cmd: Command = self._env.conf["list_dependencies_command"]
result = self._env.execute(cmd=cmd.args, stdin=StdinSource.OFF, run_id="freeze", show=False)
result.assert_success()
return result.out.splitlines()

def install(self, arguments: Any, section: str, of_type: str) -> None:
if isinstance(arguments, PythonDeps):
self._install_requirement_file(arguments, section, of_type)
Expand Down Expand Up @@ -239,4 +252,7 @@ def build_install_cmd(self, args: Sequence[str]) -> list[str]:
return install_command[:opts_at] + list(args) + install_command[opts_at + 1 :]


__all__ = ("Pip",)
__all__ = [
"Pip",
"PythonInstallerList",
]

0 comments on commit 434479f

Please sign in to comment.