Skip to content

Commit 4218b87

Browse files
paveldikovpre-commit-ci[bot]gaborbernat
authored
refactor: delegate to uv's built-in packaging and dependency handling (#180)
* refactor: delegate to uv's built-in packaging and dependency handling Fixes #151 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * PR feedback Signed-off-by: Bernát Gábor <[email protected]> * Address feedback Signed-off-by: Bernát Gábor <[email protected]> --------- Signed-off-by: Bernát Gábor <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bernát Gábor <[email protected]>
1 parent 53e0631 commit 4218b87

File tree

6 files changed

+84
-4
lines changed

6 files changed

+84
-4
lines changed

README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,15 @@ Therefore, options like `deps` are ignored (and all others
9898

9999
### `package`
100100

101-
How to install the source tree package, one of `wheel`, `editable` or `skip`. By default will do `editable`.
101+
How to install the source tree package, must be one of:
102+
103+
- `skip`,
104+
- `wheel`,
105+
- `editable` (default),
106+
- `uv` (use uv to install the project, rather than build wheel via `tox`),
107+
- `uv-editable` (use uv to install the project in editable mode, rather than build wheel via `tox`).
108+
109+
You should use the latter two in case you need to use any non-standard features of `uv`, such as `tool.uv.sources`.
102110

103111
### `extras`
104112

src/tox_uv/_installer.py

+17-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import logging
66
from collections import defaultdict
77
from collections.abc import Sequence
8+
from itertools import chain
89
from typing import TYPE_CHECKING, Any, Final
910

1011
from packaging.requirements import Requirement
@@ -16,6 +17,8 @@
1617
from tox.tox_env.python.pip.req_file import PythonDeps
1718
from uv import find_uv_bin
1819

20+
from ._package_types import UvEditablePackage, UvPackage
21+
1922
if TYPE_CHECKING:
2023
from tox.config.main import Config
2124
from tox.tox_env.package import PathPackage
@@ -94,7 +97,7 @@ def install(self, arguments: Any, section: str, of_type: str) -> None: # noqa:
9497
_LOGGER.warning("uv cannot install %r", arguments) # pragma: no cover
9598
raise SystemExit(1) # pragma: no cover
9699

97-
def _install_list_of_deps( # noqa: C901
100+
def _install_list_of_deps( # noqa: C901, PLR0912
98101
self,
99102
arguments: Sequence[
100103
Requirement | WheelPackage | SdistPackage | EditableLegacyPackage | EditablePackage | PathPackage
@@ -114,6 +117,12 @@ def _install_list_of_deps( # noqa: C901
114117
elif isinstance(arg, EditableLegacyPackage):
115118
groups["req"].extend(str(i) for i in arg.deps)
116119
groups["dev_pkg"].append(str(arg.path))
120+
elif isinstance(arg, UvPackage):
121+
extras_suffix = f"[{','.join(arg.extras)}]" if arg.extras else ""
122+
groups["uv"].append(f"{arg.path}{extras_suffix}")
123+
elif isinstance(arg, UvEditablePackage):
124+
extras_suffix = f"[{','.join(arg.extras)}]" if arg.extras else ""
125+
groups["uv_editable"].append(f"{arg.path}{extras_suffix}")
117126
else: # pragma: no branch
118127
_LOGGER.warning("uv install %r", arg) # pragma: no cover
119128
raise SystemExit(1) # pragma: no cover
@@ -129,7 +138,13 @@ def _install_list_of_deps( # noqa: C901
129138
new_deps = sorted(set(groups["req"]) - set(old or []))
130139
if new_deps: # pragma: no branch
131140
self._execute_installer(new_deps, req_of_type)
132-
install_args = ["--reinstall", "--no-deps"]
141+
install_args = ["--reinstall"]
142+
if groups["uv"]:
143+
self._execute_installer(install_args + groups["uv"], of_type)
144+
if groups["uv_editable"]:
145+
requirements = list(chain.from_iterable(("-e", entry) for entry in groups["uv_editable"]))
146+
self._execute_installer(install_args + requirements, of_type)
147+
install_args.append("--no-deps")
133148
if groups["pkg"]:
134149
self._execute_installer(install_args + groups["pkg"], of_type)
135150
if groups["dev_pkg"]:

src/tox_uv/_package.py

+15
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,31 @@
11
from __future__ import annotations
22

3+
from typing import TYPE_CHECKING
4+
35
from tox.tox_env.python.virtual_env.package.cmd_builder import VenvCmdBuilder
46
from tox.tox_env.python.virtual_env.package.pyproject import Pep517VenvPackager
57

8+
from ._package_types import UvEditablePackage, UvPackage
69
from ._venv import UvVenv
710

11+
if TYPE_CHECKING:
12+
from tox.config.sets import EnvConfigSet
13+
from tox.tox_env.package import Package
14+
815

916
class UvVenvPep517Packager(Pep517VenvPackager, UvVenv):
1017
@staticmethod
1118
def id() -> str:
1219
return "uv-venv-pep-517"
1320

21+
def perform_packaging(self, for_env: EnvConfigSet) -> list[Package]:
22+
of_type: str = for_env["package"]
23+
if of_type == UvPackage.KEY:
24+
return [UvPackage(self.core["tox_root"], for_env["extras"])]
25+
if of_type == UvEditablePackage.KEY:
26+
return [UvEditablePackage(self.core["tox_root"], for_env["extras"])]
27+
return super().perform_packaging(for_env)
28+
1429

1530
class UvVenvCmdBuilder(VenvCmdBuilder, UvVenv):
1631
@staticmethod

src/tox_uv/_package_types.py

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
4+
5+
from tox.tox_env.python.package import PythonPathPackageWithDeps
6+
7+
if TYPE_CHECKING:
8+
import pathlib
9+
from collections.abc import Sequence
10+
11+
12+
class UvBasePackage(PythonPathPackageWithDeps):
13+
"""Package to be built and installed by uv directly."""
14+
15+
KEY: str
16+
17+
def __init__(self, path: pathlib.Path, extras: Sequence[str]) -> None:
18+
super().__init__(path, ())
19+
self.extras = extras
20+
21+
22+
class UvPackage(UvBasePackage):
23+
"""Package to be built and installed by uv directly as wheel."""
24+
25+
KEY = "uv"
26+
27+
28+
class UvEditablePackage(UvBasePackage):
29+
"""Package to be built and installed by uv directly as editable wheel."""
30+
31+
KEY = "uv-editable"
32+
33+
34+
__all__ = [
35+
"UvEditablePackage",
36+
"UvPackage",
37+
]

src/tox_uv/_run.py

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from tox.tox_env.python.runner import PythonRun
88

9+
from ._package_types import UvEditablePackage, UvPackage
910
from ._venv import UvVenv
1011

1112
if TYPE_CHECKING:
@@ -32,6 +33,10 @@ def default_pkg_type(self) -> str:
3233
return "skip"
3334
return super().default_pkg_type
3435

36+
@property
37+
def _package_types(self) -> tuple[str, ...]:
38+
return *super()._package_types, UvPackage.KEY, UvEditablePackage.KEY
39+
3540

3641
__all__ = [
3742
"UvVenvRunner",

tests/test_tox_uv_package.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def test_uv_package_use_default_from_file(tox_project: ToxProjectCreator) -> Non
2424

2525

2626
@pytest.mark.parametrize("with_dash", [True, False], ids=["name_dash", "name_underscore"])
27-
@pytest.mark.parametrize("package", ["sdist", "wheel", "editable"])
27+
@pytest.mark.parametrize("package", ["sdist", "wheel", "editable", "uv", "uv-editable"])
2828
def test_uv_package_artifact(
2929
tox_project: ToxProjectCreator, package: str, demo_pkg_inline: Path, with_dash: bool
3030
) -> None:

0 commit comments

Comments
 (0)