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

pantsbuild / pants / 19529437518

20 Nov 2025 07:44AM UTC coverage: 78.884% (-1.4%) from 80.302%
19529437518

push

github

web-flow
nfpm.native_libs: Add RPM package depends from packaged pex_binaries (#22899)

## PR Series Overview

This is the second in a series of PRs that introduces a new backend:
`pants.backend.npm.native_libs`
Initially, the backend will be available as:
`pants.backend.experimental.nfpm.native_libs`

I proposed this new backend (originally named `bindeps`) in discussion
#22396.

This backend will inspect ELF bin/lib files (like `lib*.so`) in packaged
contents (for this PR series, only in `pex_binary` targets) to identify
package dependency metadata and inject that metadata on the relevant
`nfpm_deb_package` or `nfpm_rpm_package` targets. Effectively, it will
provide an approximation of these native packager features:
- `rpm`: `rpmdeps` + `elfdeps`
- `deb`: `dh_shlibdeps` + `dpkg-shlibdeps` (These substitute
`${shlibs:Depends}` in debian control files have)

### Goal: Host-agnostic package builds

This pants backend is designed to be host-agnostic, like
[nFPM](https://nfpm.goreleaser.com/).

Native packaging tools are often restricted to a single release of a
single distro. Unlike native package builders, this new pants backend
does not use any of those distro-specific or distro-release-specific
utilities or local package databases. This new backend should be able to
run (help with building deb and rpm packages) anywhere that pants can
run (MacOS, rpm linux distros, deb linux distros, other linux distros,
docker, ...).

### Previous PRs in series

- #22873

## PR Overview

This PR adds rules in `nfpm.native_libs` to add package dependency
metadata to `nfpm_rpm_package`. The 2 new rules are:

- `inject_native_libs_dependencies_in_package_fields`:

    - An implementation of the polymorphic rule `inject_nfpm_package_fields`.
      This rule is low priority (`priority = 2`) so that in-repo plugins can
      override/augment what it injects. (See #22864)

    - Rule logic overview:
        - find any pex_binaries that will be packaged in an `nfpm_rpm_package`
   ... (continued)

96 of 118 new or added lines in 3 files covered. (81.36%)

910 existing lines in 53 files now uncovered.

73897 of 93678 relevant lines covered (78.88%)

3.21 hits per line

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

42.5
/src/python/pants/bsp/context.py
1
# Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3
from __future__ import annotations
1✔
4

5
import threading
1✔
6
from collections.abc import Callable
1✔
7
from pathlib import Path
1✔
8

9
from pants.bsp.spec.lifecycle import InitializeBuildParams
1✔
10
from pants.bsp.spec.notification import BSPNotification
1✔
11

12
# Wrapper type to provide BSP rules with the ability to interact with the BSP protocol driver.
13
#
14
# Note: Due to limitations in the engine's API regarding what values can be part of a query for a union rule,
15
# this class is stored in SessionValues. See https://github.com/pantsbuild/pants/issues/12934.
16
#
17
# Concurrency: This method can be invoked from multiple threads (for each individual request). The protocol
18
# driver protects against multiple threads trying to call `initialize_connection` by only allowing
19
# the thread processing the `build/initialize` RPC to proceed; all other requests return an error _before_
20
# they enter the engine (and thus would ever have a chance to access this context).
21
#
22
# Thus, while this class can mutate due to initialization, it is immutable after it has been initialized and
23
# is thus compatible with use in the engine.
24
from pants.util.dirutil import safe_mkdtemp
1✔
25

26

27
class BSPContext:
1✔
28
    """Wrapper type to provide BSP rules with the ability to interact with the BSP protocol
29
    driver."""
30

31
    def __init__(self) -> None:
1✔
32
        """Initialize the context with an empty client params.
33

34
        This is the "connection uninitialized" state.
35
        """
UNCOV
36
        self._lock = threading.Lock()
×
UNCOV
37
        self._client_params: InitializeBuildParams | None = None
×
UNCOV
38
        self._notify_client: Callable[[BSPNotification], None] | None = None
×
UNCOV
39
        self.tempdir: Path = Path(safe_mkdtemp(prefix="bsp"))
×
40

41
    @property
1✔
42
    def is_connection_initialized(self):
1✔
UNCOV
43
        with self._lock:
×
UNCOV
44
            return self._client_params is not None
×
45

46
    @property
1✔
47
    def client_params(self) -> InitializeBuildParams:
1✔
48
        with self._lock:
×
49
            if self._client_params is None:
×
50
                raise AssertionError(
×
51
                    "Attempt to access BSP context on an uninitialized connection."
52
                )
53
            return self._client_params
×
54

55
    def initialize_connection(
1✔
56
        self, client_params: InitializeBuildParams, notify_client: Callable[[BSPNotification], None]
57
    ) -> None:
UNCOV
58
        with self._lock:
×
UNCOV
59
            if self._client_params is not None:
×
60
                raise AssertionError(
×
61
                    "Attempted to set new BSP client parameters on an already-initialized connection."
62
                )
UNCOV
63
            self._client_params = client_params
×
UNCOV
64
            self._notify_client = notify_client
×
65

66
    def notify_client(self, notification: BSPNotification) -> None:
1✔
67
        if not self.is_connection_initialized:
×
68
            return
×
69
        assert self._notify_client is not None
×
70
        self._notify_client(notification)
×
71

72
    def __hash__(self):
1✔
UNCOV
73
        return hash(self._client_params)
×
74

75
    def __eq__(self, other):
1✔
76
        if isinstance(other, BSPContext):
×
77
            return NotImplemented
×
78
        return self._client_params == other._client_params
×
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