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

pantsbuild / pants / 26380816428

25 May 2026 02:57AM UTC coverage: 52.312% (-40.6%) from 92.89%
26380816428

Pull #23368

github

web-flow
Merge 7410b48e1 into 7b1060c81
Pull Request #23368: Run Linux ARM CI on Depot runners (Cherry-pick of #23363)

31807 of 60802 relevant lines covered (52.31%)

1.05 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
2✔
5

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

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

25

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

31
    default_version = "0.11.6"
2✔
32
    default_known_versions = [
2✔
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"
2✔
38

39
    default_url_template = (
2✔
40
        "https://github.com/astral-sh/uv/releases/download/{version}/uv-{platform}.tar.gz"
41
    )
42
    default_url_platform_mapping = {
2✔
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:
2✔
49
        platform = self.default_url_platform_mapping[plat.value]
×
50
        return f"./uv-{platform}/uv"
×
51

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

55
        _executable_search_paths = StrListOption(
2✔
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(
2✔
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
2✔
82
        def path(self) -> tuple[str, ...]:
2✔
83
            def iter_path_entries():
×
84
                for entry in self._executable_search_paths:
×
85
                    if entry == "<PATH>":
×
86
                        path = self._options_env.get("PATH")
×
87
                        if path:
×
88
                            yield from path.split(os.pathsep)
×
89
                    else:
90
                        yield entry
×
91

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

94

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

100
    # The relpath to the named_cache inside the sandbox.
101
    cache_dir: ClassVar[str] = ".cache/uv_cache/"
2✔
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, ...]:
2✔
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
2✔
116
    def append_only_caches(cls) -> FrozenDict[str, str]:
2✔
117
        return FrozenDict({"uv_cache": cls.cache_dir})
×
118

119

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

128

129
def rules():
2✔
130
    return collect_rules()
2✔
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