• 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/nfpm/fields/deb.py
1
# Copyright 2023 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

UNCOV
4
from __future__ import annotations
×
5

UNCOV
6
from collections.abc import Iterable
×
UNCOV
7
from enum import Enum
×
UNCOV
8
from typing import ClassVar
×
9

UNCOV
10
from pants.backend.nfpm.fields._relationships import NfpmPackageRelationshipsField
×
UNCOV
11
from pants.backend.nfpm.fields.all import NfpmDependencies
×
UNCOV
12
from pants.backend.nfpm.fields.scripts import NfpmPackageScriptsField
×
UNCOV
13
from pants.engine.addresses import Address
×
UNCOV
14
from pants.engine.target import (
×
15
    DictStringToStringField,
16
    DictStringToStringSequenceField,
17
    InvalidFieldException,
18
    StringField,
19
)
UNCOV
20
from pants.util.frozendict import FrozenDict
×
UNCOV
21
from pants.util.strutil import help_text
×
22

23
# These fields are used by the `nfpm_deb_package` target
24
# Some fields will be duplicated by other package types which
25
# allows the help string to be packager-specific.
26

27

UNCOV
28
class NfpmDebMaintainerField(StringField):
×
UNCOV
29
    nfpm_alias = "maintainer"
×
UNCOV
30
    alias: ClassVar[str] = nfpm_alias
×
UNCOV
31
    required = True  # Not setting this is deprecated in nFPM, so we require it.
×
UNCOV
32
    value: str
×
UNCOV
33
    help = help_text(
×
34
        lambda: f"""
35
        The name and email address of the package maintainer.
36

37
        The '{NfpmDebMaintainerField.alias}' is used to identify who actually
38
        packaged the software, as opposed to the author of the software.
39

40
        The name is first, then the email address inside angle brackets `<>`
41
        (in RFC5322 format). For example: "Foo Bar <maintainer@example.com>"
42

43
        See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#maintainer
44
        """
45
    )
46
    # nFPM embeds this string as-is in the deb package.
47

48

UNCOV
49
class NfpmDebSectionField(StringField):
×
UNCOV
50
    nfpm_alias = "section"
×
UNCOV
51
    alias: ClassVar[str] = nfpm_alias
×
UNCOV
52
    help = help_text(
×
53
        """
54
        Which section, or application area, this package is part of.
55

56
        For example, you could classify your application under the "education"
57
        section, or under a language section like "python", "rust", or "ruby".
58

59
        See: https://www.debian.org/doc/debian-policy/ch-archive.html#sections
60

61
        Valid sections are listed here:
62
        https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
63
        """
64
    )
65

66

UNCOV
67
class DebPriority(Enum):
×
68
    # based on https://www.debian.org/doc/debian-policy/ch-archive.html#priorities
UNCOV
69
    required = "required"
×
UNCOV
70
    important = "important"
×
UNCOV
71
    standard = "standard"
×
UNCOV
72
    optional = "optional"
×
UNCOV
73
    extra = "extra"  # Debian notes that this is deprecated and equivalent to optional.
×
74

75

UNCOV
76
class NfpmDebPriorityField(StringField):
×
UNCOV
77
    nfpm_alias = "priority"
×
UNCOV
78
    alias: ClassVar[str] = nfpm_alias
×
UNCOV
79
    valid_choices = DebPriority
×
UNCOV
80
    default = DebPriority.optional.value
×
UNCOV
81
    value: str  # will not be None due to enum + default
×
UNCOV
82
    help = help_text(
×
83
        """
84
        Indicates how important the package is for OS functions.
85

86
        Most packages should just stick with the default priority: "optional".
87

88
        See: https://www.debian.org/doc/debian-policy/ch-archive.html#s-f-priority
89

90
        Valid priorities are listed here:
91
        https://www.debian.org/doc/debian-policy/ch-archive.html#priorities
92
        """
93
    )
94

95

UNCOV
96
class NfpmDebFieldsField(DictStringToStringField):
×
UNCOV
97
    nfpm_alias = "deb.fields"
×
UNCOV
98
    alias: ClassVar[str] = "fields"
×
UNCOV
99
    help = help_text(
×
100
        # based in part on the docs at:
101
        # https://nfpm.goreleaser.com/configuration/#reference
102
        lambda: f"""
103
        Additional fields for the control file. Empty fields are ignored.
104

105
        Debian control files supports more fields than the options that are
106
        exposed by nFPM and the pants nfpm backend. Debian even allows for
107
        user-defined fields. So, this '{NfpmDebFieldsField.alias}' field
108
        provides a way to add any additional fields to the debian control file.
109

110
        See: https://www.debian.org/doc/debian-policy/ch-controlfields.html#user-defined-fields
111
        """
112
    )
113

114

UNCOV
115
class NfpmDebTriggersField(DictStringToStringSequenceField):
×
UNCOV
116
    nfpm_alias = "deb.triggers"
×
UNCOV
117
    alias: ClassVar[str] = "triggers"
×
UNCOV
118
    help = help_text(
×
119
        """
120
        Custom deb triggers.
121

122
        nFPM uses this to create a deb triggers file, so that the package
123
        can declare its "interest" in named triggers or declare that the
124
        indicated triggers should "activate" when this package's state changes.
125

126
        The Debian documentation describes the format for the triggers file.
127
        nFPM simplifies that by accepting a dictionary from trigger directives
128
        to lists of trigger names.
129

130
        For example (note the underscore in "interest_noawait"):
131

132
        `triggers={"interest_noawait": ["some-trigger", "other-trigger"]}`
133

134
        Gets translated by nFPM into:
135

136
        ```
137
        interest-noawait some-trigger
138
        interest-noawait other-trigger
139
        ```
140

141
        See:
142
        https://wiki.debian.org/DpkgTriggers
143
        https://www.mankier.com/5/deb-triggers
144
        """
145
    )
UNCOV
146
    valid_keys = {
×
147
        # nFPM uses "_" even though the actual triggers file uses "-".
148
        "interest",
149
        "interest_await",
150
        "interest_noawait",
151
        "activate",
152
        "activate_await",
153
        "activate_noawait",
154
    }
155

UNCOV
156
    @classmethod
×
UNCOV
157
    def compute_value(
×
158
        cls, raw_value: dict[str, Iterable[str]] | None, address: Address
159
    ) -> FrozenDict[str, tuple[str, ...]] | None:
UNCOV
160
        value_or_default = super().compute_value(raw_value, address)
×
161
        # only certain keys are allowed in this dictionary.
UNCOV
162
        if value_or_default and not cls.valid_keys.issuperset(value_or_default.keys()):
×
163
            invalid_keys = value_or_default.keys() - cls.valid_keys
×
164
            raise InvalidFieldException(
×
165
                f"Each key for the '{cls.alias}' field in target {address} must be one of"
166
                f"{repr(cls.valid_keys)}, but {repr(invalid_keys)} was provided.",
167
            )
UNCOV
168
        return value_or_default
×
169

170

UNCOV
171
class NfpmDebReplacesField(NfpmPackageRelationshipsField):
×
UNCOV
172
    nfpm_alias = "replaces"
×
UNCOV
173
    alias: ClassVar[str] = nfpm_alias
×
UNCOV
174
    help = help_text(
×
175
        lambda: f"""
176
        A list of packages that this package replaces or partially replaces.
177

178
        To declare that this package partially replaces another package, by
179
        taking ownership of files in that package, include that other package in
180
        both '{NfpmDebReplacesField.alias}' and '{NfpmDebBreaksField.alias}'.
181

182
        If this package completely replaces the other package, you can force its
183
        removal by including the other package in both '{NfpmDebReplacesField.alias}'
184
        and '{NfpmDebConflictsField.alias}' (and '{NfpmDebProvidesField.alias}' if it
185
        is a virtual package).
186

187
        See: https://www.debian.org/doc/debian-policy/ch-relationships.html#overwriting-files-and-replacing-packages-replaces
188
        """
189
    )
190

191

UNCOV
192
class NfpmDebProvidesField(NfpmPackageRelationshipsField):
×
UNCOV
193
    nfpm_alias = "provides"
×
UNCOV
194
    alias: ClassVar[str] = nfpm_alias
×
UNCOV
195
    help = help_text(
×
196
        lambda: f"""
197
        A list of virtual packages that this package provides.
198

199
        Each entry can be either a package name, or a package name with a version.
200
        The version, however, must be declared with `=` (not `<<`, `<=`, etc)
201

202
        For example, these declare virtual packages foo and bar.
203

204
          - "foo"
205
          - "bar (=1.0.0)"
206

207
        If several packages declare the same '{NfpmDebProvidesField.alias}',
208
        then they might need to declare that they conflict with each other
209
        using '{NfpmDebConflictsField.alias}' if, for example, they also install
210
        a binary with the same path.
211

212
        See: https://www.debian.org/doc/debian-policy/ch-relationships.html#virtual-packages-provides
213
        """
214
    )
215

216

UNCOV
217
class NfpmDebDependsField(NfpmPackageRelationshipsField):
×
UNCOV
218
    nfpm_alias = "depends"
×
UNCOV
219
    alias: ClassVar[str] = nfpm_alias
×
UNCOV
220
    help = help_text(
×
221
        lambda: f"""
222
        List of package dependencies (for package installers).
223

224
        The '{NfpmDebDependsField.alias}' field has install-time dependencies
225
        that can use version selectors (with one of `<<`, `<=`, `=`, `>=`, `>>`
226
        in parentheses) or use `|` to specify package alternatives that equally
227
        satisfy a dependency.
228

229
          - "git"
230
          - "libc6 (>= 2.2.1)"
231
          - "default-mta | mail-transport-agent"
232

233
        Make sure to include package dependencies of this package as well as any
234
        packages required by the `postinstall`, `postupgrade`, or `preremove` scripts.
235

236
        WARNING: This is NOT the same as the 'dependencies' field!
237
        It does not accept pants-style dependencies like target addresses.
238

239
        See: https://www.debian.org/doc/debian-policy/ch-relationships.html
240
        """
241
    )
242

243

UNCOV
244
class NfpmDebPreDependsField(NfpmPackageRelationshipsField):
×
UNCOV
245
    nfpm_alias = "deb.predepends"
×
UNCOV
246
    alias: ClassVar[str] = "predepends"
×
UNCOV
247
    help = help_text(
×
248
        lambda: f"""
249
        List of package unpack-time dependencies (for package installers).
250

251
        In most cases, you should use the '{NfpmDebDependsField.alias}' field
252
        instead of this one to declare install-time package dependencies.
253
        The '{NfpmDebPreDependsField.alias}' field has install-time dependencies
254
        that need to be available (including unpacking, pre-install, and
255
        post-install scripts) before unpacking or installing this package.
256

257
        Make sure to include packages required by the `preinst` script.
258

259
        WARNING: This is NOT the same as the 'dependencies' field!
260
        It does not accept pants-style dependencies like target addresses.
261

262
        See: https://www.debian.org/doc/debian-policy/ch-relationships.html
263
        """
264
    )
265

266

UNCOV
267
class NfpmDebRecommendsField(NfpmPackageRelationshipsField):
×
UNCOV
268
    nfpm_alias = "recommends"
×
UNCOV
269
    alias: ClassVar[str] = nfpm_alias
×
UNCOV
270
    help = help_text(
×
271
        lambda: f"""
272
        List of optional package dependencies (for package installers).
273

274
        The '{NfpmDebRecommendsField.alias}' field has packages that can be
275
        excluded in "unusual installations" but should generally be installed
276
        with this package.
277

278
        WARNING: This is NOT the same as the 'dependencies' field!
279
        It does not accept pants-style dependencies like target addresses.
280

281
        See: https://www.debian.org/doc/debian-policy/ch-relationships.html
282
        """
283
    )
284

285

UNCOV
286
class NfpmDebSuggestsField(NfpmPackageRelationshipsField):
×
UNCOV
287
    nfpm_alias = "suggests"
×
UNCOV
288
    alias: ClassVar[str] = nfpm_alias
×
UNCOV
289
    help = help_text(
×
290
        """
291
        A list of package suggestions (for package installers).
292

293
        These packages are completely optional, but could be useful for users
294
        of this package to install as well.
295

296
        See: https://www.debian.org/doc/debian-policy/ch-relationships.html
297
        """
298
    )
299

300

UNCOV
301
class NfpmDebConflictsField(NfpmPackageRelationshipsField):
×
UNCOV
302
    nfpm_alias = "conflicts"
×
UNCOV
303
    alias: ClassVar[str] = nfpm_alias
×
UNCOV
304
    help = help_text(
×
305
        lambda: f"""
306
        A list of packages that this package conflicts with.
307

308
        Generally, you should use '{NfpmDebBreaksField.alias}' instead of
309
        '{NfpmDebConflictsField.alias}', because '{NfpmDebConflictsField.alias}'
310
        imposes much more strict requirements on the order of package installs
311
        and removals. Use this if the conflicting packages must be completely
312
        uninstalled before this package can be installed.
313

314
        For example, this is how to declare that this package conflicts with the
315
        foo (version 2.5 or less) and bar packages, so they must be uninstalled
316
        before this package can be installed.
317

318
          - "foo (<2.6)"
319
          - "bar"
320

321
        See: https://www.debian.org/doc/debian-policy/ch-relationships.html#conflicting-binary-packages-conflicts
322
        """
323
    )
324

325

UNCOV
326
class NfpmDebBreaksField(NfpmPackageRelationshipsField):
×
UNCOV
327
    nfpm_alias = "deb.breaks"
×
UNCOV
328
    alias: ClassVar[str] = "breaks"
×
UNCOV
329
    help = help_text(
×
330
        lambda: f"""
331
        A list of packages which would break if this package would be installed.
332

333
        The installation of this package is blocked (by package installers)
334
        if any packages in this list are already installed. This is a looser
335
        package relationship than the '{NfpmDebConflictsField.alias}' field,
336
        because it allows the package installer more flexibility on ordering
337
        package installs and removals (For example, if this package breaks "bar",
338
        then "bar" can be removed after this package when it gets removed in the
339
        same package install transaction).
340

341
        For example, this is how to declare that this breaks package foo, but
342
        only if foo version 2.5 or less is installed and it breaks package bar
343
        no matter what version is installed.
344

345
          - "foo (<2.6)"
346
          - "bar"
347

348
        See: https://www.debian.org/doc/debian-policy/ch-relationships.html#packages-which-break-other-packages-breaks
349
        """
350
    )
351

352

UNCOV
353
class NfpmDebCompressionAlgorithm(Enum):
×
354
    # This is what nFPM implements.
UNCOV
355
    gzip = "gzip"
×
UNCOV
356
    none = "none"
×
UNCOV
357
    xz = "xz"
×
UNCOV
358
    zstd = "zstd"
×
359

360

UNCOV
361
class NfpmDebCompressionField(StringField):
×
UNCOV
362
    nfpm_alias = "deb.compression"
×
UNCOV
363
    alias: ClassVar[str] = "compression"
×
UNCOV
364
    valid_choices = NfpmDebCompressionAlgorithm
×
UNCOV
365
    default = NfpmDebCompressionAlgorithm.gzip.value  # same default as nFPM
×
UNCOV
366
    value: str  # will not be None due to enum + default
×
UNCOV
367
    help = help_text(
×
368
        """
369
        The compression algorithm to use on the deb package.
370
        """
371
    )
372

373

UNCOV
374
class NfpmDebScriptsField(NfpmPackageScriptsField):
×
UNCOV
375
    nfpm_aliases: ClassVar[FrozenDict[str, str]] = FrozenDict(
×
376
        {
377
            **NfpmPackageScriptsField.nfpm_aliases,
378
            "rules": "deb.scripts.rules",
379
            "templates": "deb.scripts.templates",
380
            "config": "deb.scripts.config",
381
        }
382
    )
UNCOV
383
    help = help_text(
×
384
        f"""
385
        Map of maintainer script source files for the deb package.
386

387
        This maps the script type (key) to the script source file (value).
388
        Each of the script source file(s) must be provided via '{NfpmDependencies.alias}'.
389
        The script types are the names used by nFPM. For reference, Debian
390
        uses the following file names instead:
391

392
        | nFPM script | Debian file |
393
        +-------------+-------------+
394
        | preinstall  | preinst     |
395
        | postinstall | postinst    |
396
        | preremove   | prerm       |
397
        | postremove  | postrm      |
398
        | config      | config      |
399
        | templates   | templates   |
400
        | rules       | rules       |
401

402
        The `pre*` and `post*` scripts are used by `dpkg` at various stages of
403
        installing, upgrading, and removing the deb package.
404

405
        The `config` script and `templates` file are part of the Debian Configuration
406
        Management Specification. `config` can run at any time, including before
407
        `preinst` to prompt the user for package configuration using `debconf`.
408
        `templates` is used by `debconf` to create those prompts.
409

410
        The `rules` script is only needed for source packages. This script is an
411
        executable makefile that can build a binary from the packaged sources.
412

413
        Please consult the Debian docs to understand when `dpkg` or `debconf` will
414
        run each of these scripts, what assumptions you can safely make when they run,
415
        and how `dpkg` handles a failure.
416

417
        See:
418
        https://www.debian.org/doc/debian-policy/ch-binary.html#maintainer-scripts
419
        https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
420
        https://www.debian.org/doc/debian-policy/ap-flowcharts.html
421
        http://www.fifi.org/doc/debconf-doc/tutorial.html
422
        https://www.debian.org/doc/debian-policy/ch-source.html#s-debianrules
423
        """
424
    )
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