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

pantsbuild / pants / 19015773527

02 Nov 2025 05:33PM UTC coverage: 17.872% (-62.4%) from 80.3%
19015773527

Pull #22816

github

web-flow
Merge a12d75757 into 6c024e162
Pull Request #22816: Update Pants internal Python to 3.14

4 of 5 new or added lines in 3 files covered. (80.0%)

28452 existing lines in 683 files now uncovered.

9831 of 55007 relevant lines covered (17.87%)

0.18 hits per line

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

0.0
/src/python/pants/backend/python/macros/uv_requirements.py
1
# Copyright 2024 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

UNCOV
4
import logging
×
UNCOV
5
from collections.abc import Iterator
×
UNCOV
6
from functools import partial
×
UNCOV
7
from pathlib import PurePath
×
8

UNCOV
9
from pants.backend.python.macros.common_fields import (
×
10
    ModuleMappingField,
11
    RequirementsOverrideField,
12
    TypeStubsModuleMappingField,
13
)
UNCOV
14
from pants.backend.python.macros.common_requirements_rule import _generate_requirements
×
UNCOV
15
from pants.backend.python.macros.poetry_requirements import PyProjectToml
×
UNCOV
16
from pants.backend.python.subsystems.setup import PythonSetup
×
UNCOV
17
from pants.backend.python.target_types import PythonRequirementResolveField, PythonRequirementTarget
×
UNCOV
18
from pants.base.build_root import BuildRoot
×
UNCOV
19
from pants.engine.rules import collect_rules, rule
×
UNCOV
20
from pants.engine.target import (
×
21
    COMMON_TARGET_FIELDS,
22
    GeneratedTargets,
23
    GenerateTargetsRequest,
24
    SingleSourceField,
25
    TargetGenerator,
26
)
UNCOV
27
from pants.engine.unions import UnionMembership, UnionRule
×
UNCOV
28
from pants.util.logging import LogLevel
×
UNCOV
29
from pants.util.pip_requirement import PipRequirement
×
UNCOV
30
from pants.util.strutil import softwrap
×
31

UNCOV
32
logger = logging.getLogger(__name__)
×
33

34

UNCOV
35
def parse_pyproject_toml(pyproject_toml: PyProjectToml) -> Iterator[PipRequirement]:
×
36
    parsed = pyproject_toml.parse()
×
37
    try:
×
38
        uv_vals = parsed["tool"]["uv"]
×
39
    except KeyError:
×
40
        raise KeyError(
×
41
            softwrap(
42
                f"""
43
                No section `tool.uv` found in {pyproject_toml.toml_relpath}, which
44
                is loaded by Pants from a `uv_requirements` macro.
45

46
                Did you mean to set up uv?
47
                """
48
            )
49
        )
50

51
    # See https://docs.astral.sh/uv/concepts/dependencies/#development-dependencies
52
    # This should be a list of PEP 508 compliant strings.
53
    dev_dependencies = uv_vals.get("dev-dependencies", [])
×
54
    if not dev_dependencies:
×
55
        logger.warning(
×
56
            softwrap(
57
                f"""
58
                No requirements defined in `tool.uv.dev-dependencies` in {pyproject_toml.toml_relpath},
59
                which is loaded by Pants from a uv_requirements macro. Did you mean to populate
60
                this section with requirements?.
61
                """
62
            )
63
        )
64

65
    for dep in dev_dependencies:
×
66
        dep = dep.strip()
×
67
        if not dep or dep.startswith("#"):
×
68
            continue
×
69
        yield PipRequirement.parse(dep, description_of_origin=str(pyproject_toml.toml_relpath))
×
70

71

UNCOV
72
def parse_uv_requirements(
×
73
    build_root: BuildRoot, file_contents: bytes, file_path: str
74
) -> set[PipRequirement]:
75
    return set(
×
76
        parse_pyproject_toml(
77
            PyProjectToml(
78
                build_root=PurePath(build_root.path),
79
                toml_relpath=PurePath(file_path),
80
                toml_contents=file_contents.decode(),
81
            )
82
        )
83
    )
84

85

86
# ---------------------------------------------------------------------------------
87
# Target generator
88
# ---------------------------------------------------------------------------------
89

90

UNCOV
91
class UvRequirementsSourceField(SingleSourceField):
×
UNCOV
92
    default = "pyproject.toml"
×
UNCOV
93
    required = False
×
94

95

UNCOV
96
class UvRequirementsTargetGenerator(TargetGenerator):
×
UNCOV
97
    alias = "uv_requirements"
×
UNCOV
98
    help = "Generate a `python_requirement` for each entry in `pyproject.toml` under the `[tool.uv]` section."
×
UNCOV
99
    generated_target_cls = PythonRequirementTarget
×
100
    # Note that this does not have a `dependencies` field.
UNCOV
101
    core_fields = (
×
102
        *COMMON_TARGET_FIELDS,
103
        ModuleMappingField,
104
        TypeStubsModuleMappingField,
105
        UvRequirementsSourceField,
106
        RequirementsOverrideField,
107
    )
UNCOV
108
    copied_fields = COMMON_TARGET_FIELDS
×
UNCOV
109
    moved_fields = (PythonRequirementResolveField,)
×
110

111

UNCOV
112
class GenerateFromUvRequirementsRequest(GenerateTargetsRequest):
×
UNCOV
113
    generate_from = UvRequirementsTargetGenerator
×
114

115

UNCOV
116
@rule(desc="Generate `python_requirement` targets from uv pyproject.toml", level=LogLevel.DEBUG)
×
UNCOV
117
async def generate_from_uv_requirement(
×
118
    request: GenerateFromUvRequirementsRequest,
119
    build_root: BuildRoot,
120
    union_membership: UnionMembership,
121
    python_setup: PythonSetup,
122
) -> GeneratedTargets:
123
    result = await _generate_requirements(
×
124
        request,
125
        union_membership,
126
        python_setup,
127
        parse_requirements_callback=partial(parse_uv_requirements, build_root),
128
    )
129
    return GeneratedTargets(request.generator, result)
×
130

131

UNCOV
132
def rules():
×
UNCOV
133
    return (
×
134
        *collect_rules(),
135
        UnionRule(GenerateTargetsRequest, GenerateFromUvRequirementsRequest),
136
    )
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

© 2025 Coveralls, Inc