44
55import logging
66from collections import defaultdict
7- from typing import TYPE_CHECKING , Any , Sequence , cast
7+ from typing import TYPE_CHECKING , Any , Sequence
88
99from packaging .requirements import Requirement
1010from packaging .utils import parse_sdist_filename , parse_wheel_filename
11- from tox .config .of_type import ConfigDynamicDefinition
1211from tox .config .types import Command
13- from tox .execute .request import StdinSource
1412from tox .tox_env .errors import Fail , Recreate
1513from tox .tox_env .python .package import EditableLegacyPackage , EditablePackage , SdistPackage , WheelPackage
16- from tox .tox_env .python .pip .pip_install import Pip
14+ from tox .tox_env .python .pip .pip_install import Pip , PythonInstallerListDependencies
1715from tox .tox_env .python .pip .req_file import PythonDeps
1816from uv import find_uv_bin
1917
2018if TYPE_CHECKING :
2119 from tox .config .main import Config
2220 from tox .tox_env .package import PathPackage
21+ from tox .tox_env .python .api import Python
2322
2423
25- class UvInstaller (Pip ):
24+ class ReadOnlyUvInstaller (PythonInstallerListDependencies ):
25+ def __init__ (self , tox_env : Python , with_list_deps : bool = True ) -> None : # noqa: FBT001, FBT002
26+ self ._with_list_deps = with_list_deps
27+ super ().__init__ (tox_env )
28+
29+ def freeze_cmd (self ) -> list [str ]:
30+ return [self .uv , "--color" , "never" , "pip" , "freeze" ]
31+
32+ @property
33+ def uv (self ) -> str :
34+ return find_uv_bin ()
35+
36+ def install (self , arguments : Any , section : str , of_type : str ) -> None : # noqa: ANN401
37+ raise NotImplementedError # not supported
38+
39+
40+ class UvInstaller (ReadOnlyUvInstaller , Pip ):
2641 """Pip is a python installer that can install packages as defined by PEP-508 and PEP-517."""
2742
2843 def _register_config (self ) -> None :
@@ -42,13 +57,6 @@ def uv_resolution_post_process(value: str) -> str:
4257 desc = "Define the resolution strategy for uv" ,
4358 post_process = uv_resolution_post_process ,
4459 )
45- if self ._with_list_deps : # pragma: no branch
46- conf = cast (ConfigDynamicDefinition [Command ], self ._env .conf ._defined ["list_dependencies_command" ]) # noqa: SLF001
47- conf .default = Command ([self .uv , "--color" , "never" , "pip" , "freeze" ])
48-
49- @property
50- def uv (self ) -> str :
51- return find_uv_bin ()
5260
5361 def default_install_command (self , conf : Config , env_name : str | None ) -> Command : # noqa: ARG002
5462 cmd = [self .uv , "pip" , "install" , "{opts}" , "{packages}" ]
@@ -78,12 +86,6 @@ def post_process_install_command(self, cmd: Command) -> Command:
7886 install_command .pop (opts_at )
7987 return cmd
8088
81- def installed (self ) -> list [str ]:
82- cmd : Command = self ._env .conf ["list_dependencies_command" ]
83- result = self ._env .execute (cmd = cmd .args , stdin = StdinSource .OFF , run_id = "freeze" , show = False )
84- result .assert_success ()
85- return result .out .splitlines ()
86-
8789 def install (self , arguments : Any , section : str , of_type : str ) -> None : # noqa: ANN401
8890 if isinstance (arguments , PythonDeps ):
8991 self ._install_requirement_file (arguments , section , of_type )
@@ -138,5 +140,6 @@ def _install_list_of_deps( # noqa: C901
138140
139141
140142__all__ = [
143+ "ReadOnlyUvInstaller" ,
141144 "UvInstaller" ,
142145]
0 commit comments