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

pantsbuild / pants / 19120576134

06 Nov 2025 12:22AM UTC coverage: 80.307% (+0.007%) from 80.3%
19120576134

Pull #22861

github

web-flow
Merge 9479b1cb5 into 89462b7ef
Pull Request #22861: nfpm.native_libs: new backend to generate pkg deps for nfpm packages

613 of 767 new or added lines in 18 files covered. (79.92%)

1 existing line in 1 file now uncovered.

78600 of 97875 relevant lines covered (80.31%)

3.35 hits per line

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

68.42
/src/python/pants/backend/nfpm/util_rules/inject_config_test.py
1
# Copyright 2025 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
1✔
5

6
from textwrap import dedent
1✔
7
from typing import Any
1✔
8

9
import pytest
1✔
10

11
from pants.backend.nfpm.fields.all import NfpmPlatformField
1✔
12
from pants.backend.nfpm.fields.version import NfpmVersionField, NfpmVersionReleaseField
1✔
13
from pants.backend.nfpm.target_types import target_types as nfpm_target_types
1✔
14
from pants.backend.nfpm.target_types_rules import rules as nfpm_target_types_rules
1✔
15
from pants.backend.nfpm.util_rules.inject_config import (
1✔
16
    InjectedNfpmPackageFields,
17
    InjectNfpmPackageFieldsRequest,
18
    NfpmPackageTargetWrapper,
19
)
20
from pants.backend.nfpm.util_rules.inject_config import rules as nfpm_inject_config_rules
1✔
21
from pants.engine.internals.native_engine import Address, Field
1✔
22
from pants.engine.rules import QueryRule, rule
1✔
23
from pants.engine.unions import UnionRule
1✔
24
from pants.testutil.rule_runner import RuleRunner
1✔
25

26
_PKG_NAME = "pkg"
1✔
27

28

29
class PluginInjectFieldsRequest(InjectNfpmPackageFieldsRequest):
1✔
30
    @classmethod
1✔
31
    def is_applicable(cls, _) -> bool:
1✔
32
        return True
×
33

34

35
@rule
1✔
36
async def inject_nfpm_package_fields_plugin(
1✔
37
    request: PluginInjectFieldsRequest,
38
) -> InjectedNfpmPackageFields:
39
    address = request.target.address
×
40
    # preserve fields from earlier rules in chain
NEW
41
    fields: list[Field] = list(request.injected_fields.values())
×
NEW
42
    if NfpmVersionField not in request.injected_fields:
×
NEW
43
        fields.extend(
×
44
            [
45
                NfpmVersionField("9.8.7-dev+git", address),
46
                NfpmVersionReleaseField(6, address),
47
            ]
48
        )
UNCOV
49
    return InjectedNfpmPackageFields(fields, address=address)
×
50

51

52
class SubclassPluginInjectFieldsRequest(PluginInjectFieldsRequest):
1✔
53
    pass
1✔
54

55

56
@rule
1✔
57
async def inject_nfpm_package_fields_subclass(
1✔
58
    request: SubclassPluginInjectFieldsRequest,
59
) -> InjectedNfpmPackageFields:
NEW
60
    address = request.target.address
×
61
    # preserve fields from earlier rules in chain
NEW
62
    fields: list[Field] = list(request.injected_fields.values())
×
NEW
63
    if not fields or NfpmVersionReleaseField in request.injected_fields:
×
NEW
64
        release = 0
×
NEW
65
        if NfpmVersionReleaseField in request.injected_fields:
×
NEW
66
            old_release = request.injected_fields[NfpmVersionReleaseField].value
×
NEW
67
            assert old_release is not None
×
NEW
68
            release = 10 + old_release
×
NEW
69
        fields.append(NfpmVersionReleaseField(release, address))
×
NEW
70
    return InjectedNfpmPackageFields(fields, address=address)
×
71

72

73
class HighPriorityInjectFieldsRequest(InjectNfpmPackageFieldsRequest):
1✔
74
    priority = 100
1✔
75

76
    @classmethod
1✔
77
    def is_applicable(cls, _) -> bool:
1✔
NEW
78
        return True
×
79

80
    @classmethod
1✔
81
    def lt_fallback(cls, other: Any) -> bool:
1✔
NEW
82
        return False
×
83

84

85
@rule
1✔
86
async def inject_nfpm_package_fields_high_priority(
1✔
87
    request: HighPriorityInjectFieldsRequest,
88
) -> InjectedNfpmPackageFields:
NEW
89
    address = request.target.address
×
90
    # preserve fields from earlier rules in chain
NEW
91
    fields: list[Field] = list(request.injected_fields.values())
×
NEW
92
    if not fields or NfpmVersionField not in request.injected_fields:
×
NEW
93
        fields.extend(
×
94
            [
95
                NfpmVersionField("9.9.9-dev+git", address),
96
                NfpmVersionReleaseField(9, address),
97
            ]
98
        )
99
    # The high priority implementation that wants to force Platform to always be "foobar"
100
    # even if another rule injected NfpmPlatformField
NEW
101
    fields.append(NfpmPlatformField("foobar", address))
×
NEW
102
    return InjectedNfpmPackageFields(fields, address=address)
×
103

104

105
@pytest.mark.parametrize(
1✔
106
    "a,b,expected_lt",
107
    (
108
        # HighPriority* > SubclassPlugin* > Plugin*
109
        (HighPriorityInjectFieldsRequest, SubclassPluginInjectFieldsRequest, False),
110
        (HighPriorityInjectFieldsRequest, PluginInjectFieldsRequest, False),
111
        (SubclassPluginInjectFieldsRequest, HighPriorityInjectFieldsRequest, True),
112
        (SubclassPluginInjectFieldsRequest, PluginInjectFieldsRequest, False),
113
        (PluginInjectFieldsRequest, HighPriorityInjectFieldsRequest, True),
114
        (PluginInjectFieldsRequest, SubclassPluginInjectFieldsRequest, True),
115
        # self is equal which is not less than
116
        (HighPriorityInjectFieldsRequest, HighPriorityInjectFieldsRequest, False),
117
    ),
118
)
119
def test_nfpm_package_fields_request_class_sort(a: Any, b: Any, expected_lt):
1✔
120
    ret = a < b
1✔
121
    assert ret == expected_lt, f"a.priority={a.priority} b.priority={b.priority}"
1✔
122

123

124
@pytest.fixture
1✔
125
def rule_runner() -> RuleRunner:
1✔
126
    rule_runner = RuleRunner(
1✔
127
        target_types=[
128
            *nfpm_target_types(),
129
        ],
130
        rules=[
131
            *nfpm_target_types_rules(),
132
            *nfpm_inject_config_rules(),
133
            inject_nfpm_package_fields_plugin,
134
            inject_nfpm_package_fields_subclass,
135
            inject_nfpm_package_fields_high_priority,
136
            UnionRule(InjectNfpmPackageFieldsRequest, PluginInjectFieldsRequest),
137
            UnionRule(InjectNfpmPackageFieldsRequest, SubclassPluginInjectFieldsRequest),
138
            UnionRule(InjectNfpmPackageFieldsRequest, HighPriorityInjectFieldsRequest),
139
            QueryRule(InjectedNfpmPackageFields, (NfpmPackageTargetWrapper,)),
140
        ],
141
    )
142
    rule_runner.set_options([], env_inherit={"PATH", "PYENV_ROOT", "HOME"})
1✔
143
    return rule_runner
1✔
144

145

146
@pytest.mark.parametrize(
1✔
147
    "packager",
148
    (
149
        "apk",
150
        "archlinux",
151
        "deb",
152
        "rpm",
153
    ),
154
)
155
def test_determine_injected_nfpm_package_fields(rule_runner: RuleRunner, packager: str) -> None:
1✔
156
    packager = "deb"
1✔
157
    rule_runner.write_files(
1✔
158
        {
159
            "BUILD": dedent(
160
                f"""
161
                nfpm_{packager}_package(
162
                    name="{_PKG_NAME}",
163
                    description="A {packager} package",
164
                    package_name="{_PKG_NAME}",
165
                    version="",  # the plugin should provide this
166
                    {"" if packager != "deb" else 'maintainer="Foo Bar <deb@example.com>",'}
167
                    dependencies=[],
168
                )
169
                """
170
            ),
171
        }
172
    )
173
    target = rule_runner.get_target(Address("", target_name=_PKG_NAME))
1✔
174
    result = rule_runner.request(InjectedNfpmPackageFields, [NfpmPackageTargetWrapper(target)])
1✔
175
    field_values = result.field_values
1✔
176
    assert len(field_values) == 3
1✔
177
    assert field_values[NfpmVersionField].value == "9.8.7-dev+git"  # (Plugin*)
1✔
178
    assert field_values[NfpmVersionReleaseField].value == 16  # 6 (Plugin*) + 10 (SubclassPlugin*)
1✔
179
    assert field_values[NfpmPlatformField].value == "foobar"  # (HighPriority*)
1✔
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