• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 26260209689

21 May 2026 11:59PM UTC coverage: 75.453% (-15.7%) from 91.156%
26260209689

Pull #23365

github

web-flow
Merge 5fe873b58 into 7ea655ba0
Pull Request #23365: uv.lock -> pex optimization

5 of 16 new or added lines in 1 file covered. (31.25%)

10118 existing lines in 378 files now uncovered.

54669 of 72454 relevant lines covered (75.45%)

2.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.44
/src/python/pants/backend/python/subsystems/uv.py
1
# Copyright 2026 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
5✔
5

6
import os
5✔
7
from dataclasses import dataclass
5✔
8
from typing import ClassVar
5✔
9

10
from pants.core.util_rules.external_tool import (
5✔
11
    TemplatedExternalTool,
12
    download_external_tool,
13
)
14
from pants.engine.env_vars import EXTRA_ENV_VARS_USAGE_HELP
5✔
15
from pants.engine.fs import Digest
5✔
16
from pants.engine.internals.native_engine import FrozenDict
5✔
17
from pants.engine.platform import Platform
5✔
18
from pants.engine.rules import collect_rules, rule
5✔
19
from pants.option.option_types import StrListOption
5✔
20
from pants.option.subsystem import Subsystem
5✔
21
from pants.util.memo import memoized_property
5✔
22
from pants.util.ordered_set import OrderedSet
5✔
23
from pants.util.strutil import softwrap
5✔
24

25

26
class Uv(TemplatedExternalTool):
5✔
27
    options_scope = "uv"
5✔
28
    name = "uv"
5✔
29
    help = "The uv Python package manager (https://github.com/astral-sh/uv)."
5✔
30

31
    default_version = "0.11.6"
5✔
32
    default_known_versions = [
5✔
33
        "0.11.6|macos_arm64 |4b69a4e366ec38cd5f305707de95e12951181c448679a00dce2a78868dfc9f5b|20807020",
34
        "0.11.6|linux_x86_64|aa342a53abe42364093506d7704214d2cdca30b916843e520bc67759a5d20132|24460747",
35
        "0.11.6|linux_arm64 |d14ebd6f200047264152daaf97b8bd36c7885a5033e9e8bba8366cb0049c0d00|22576913",
36
    ]
37
    version_constraints = ">=0.7.4,<1.0"
5✔
38

39
    default_url_template = (
5✔
40
        "https://github.com/astral-sh/uv/releases/download/{version}/uv-{platform}.tar.gz"
41
    )
42
    default_url_platform_mapping = {
5✔
43
        "linux_arm64": "aarch64-unknown-linux-musl",
44
        "linux_x86_64": "x86_64-unknown-linux-musl",
45
        "macos_arm64": "aarch64-apple-darwin",
46
    }
47

48
    def generate_exe(self, plat: Platform) -> str:
5✔
UNCOV
49
        platform = self.default_url_platform_mapping[plat.value]
×
UNCOV
50
        return f"./uv-{platform}/uv"
×
51

52
    class EnvironmentAware(Subsystem.EnvironmentAware):
5✔
53
        env_vars_used_by_options = ("PATH",)
5✔
54

55
        _executable_search_paths = StrListOption(
5✔
56
            default=["<PATH>"],
57
            help=softwrap(
58
                """
59
                The PATH value that will be used by the uv subprocess and any subprocesses it
60
                spawns.
61

62
                The special string `"<PATH>"` will expand to the contents of the PATH env var.
63
                """
64
            ),
65
            advanced=True,
66
            metavar="<binary-paths>",
67
        )
68

69
        extra_env_vars = StrListOption(
5✔
70
            help=softwrap(
71
                f"""
72
                Additional environment variables to pass to `uv` subprocesses.
73
                Can be used to pass `UV_KEYRING_PROVIDER`, or private-index credentials such as
74
                `UV_INDEX_<NAME>_USERNAME`/`UV_INDEX_<NAME>_PASSWORD`.
75

76
                {EXTRA_ENV_VARS_USAGE_HELP}
77
                """
78
            ),
79
        )
80

81
        @memoized_property
5✔
82
        def path(self) -> tuple[str, ...]:
5✔
UNCOV
83
            def iter_path_entries():
×
UNCOV
84
                for entry in self._executable_search_paths:
×
UNCOV
85
                    if entry == "<PATH>":
×
UNCOV
86
                        path = self._options_env.get("PATH")
×
UNCOV
87
                        if path:
×
UNCOV
88
                            yield from path.split(os.pathsep)
×
89
                    else:
90
                        yield entry
×
91

UNCOV
92
            return tuple(OrderedSet(iter_path_entries()))
×
93

94

95
@dataclass(frozen=True)
5✔
96
class DownloadedUv:
5✔
97
    digest: Digest
5✔
98
    exe: str
5✔
99

100
    # The relpath to the named_cache inside the sandbox.
101
    cache_dir: ClassVar[str] = ".cache/uv_cache/"
5✔
102

103
    # Initial command line args for all invocations of this uv.
104
    # Callers will want to add further args for specific invocations.
105
    def args(self) -> tuple[str, ...]:
5✔
UNCOV
106
        return (
×
107
            self.exe,
108
            # --no-config suppresses user and host config discovery.
109
            "--no-config",
110
            # --config-file forces use of our generated uv.toml instead.
111
            "--config-file=uv.toml",
112
            f"--cache-dir={self.cache_dir}",
113
        )
114

115
    @classmethod
5✔
116
    def append_only_caches(cls) -> FrozenDict[str, str]:
5✔
UNCOV
117
        return FrozenDict({"uv_cache": cls.cache_dir})
×
118

119

120
@rule
5✔
121
async def download_uv_binary(uv: Uv, platform: Platform) -> DownloadedUv:
5✔
UNCOV
122
    downloaded = await download_external_tool(uv.get_request(platform))
×
UNCOV
123
    return DownloadedUv(
×
124
        digest=downloaded.digest,
125
        exe=downloaded.exe,
126
    )
127

128

129
def rules():
5✔
130
    return collect_rules()
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc