• 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/shell/goals/package.py
1
# Copyright 2025 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
import dataclasses
×
UNCOV
7
from dataclasses import dataclass
×
8

UNCOV
9
from pants.backend.shell.target_types import (
×
10
    ShellCommandCommandField,
11
    ShellCommandPackageDependenciesField,
12
    SkipShellCommandPackageField,
13
)
UNCOV
14
from pants.backend.shell.util_rules import shell_command
×
UNCOV
15
from pants.backend.shell.util_rules.shell_command import (
×
16
    ShellCommandProcessFromTargetRequest,
17
    prepare_process_request_from_target,
18
)
UNCOV
19
from pants.core.environments.target_types import EnvironmentField
×
UNCOV
20
from pants.core.goals.package import (
×
21
    BuiltPackage,
22
    BuiltPackageArtifact,
23
    OutputPathField,
24
    PackageFieldSet,
25
)
UNCOV
26
from pants.core.util_rules.adhoc_process_support import AdhocProcessRequest
×
UNCOV
27
from pants.core.util_rules.adhoc_process_support import rules as adhoc_process_support_rules
×
UNCOV
28
from pants.core.util_rules.adhoc_process_support import run_prepared_adhoc_process
×
UNCOV
29
from pants.engine.fs import EMPTY_DIGEST, AddPrefix, Digest
×
UNCOV
30
from pants.engine.internals.graph import resolve_target
×
UNCOV
31
from pants.engine.intrinsics import add_prefix, get_digest_entries
×
UNCOV
32
from pants.engine.process import ProcessCacheScope
×
UNCOV
33
from pants.engine.rules import collect_rules, implicitly, rule
×
UNCOV
34
from pants.engine.target import Target, WrappedTargetRequest
×
UNCOV
35
from pants.engine.unions import UnionRule
×
UNCOV
36
from pants.util.logging import LogLevel
×
37

38

UNCOV
39
@dataclass(frozen=True)
×
UNCOV
40
class PackageShellCommandFieldSet(PackageFieldSet):
×
UNCOV
41
    required_fields = (
×
42
        ShellCommandCommandField,
43
        ShellCommandPackageDependenciesField,
44
    )
45

UNCOV
46
    environment: EnvironmentField
×
UNCOV
47
    output_path: OutputPathField
×
48

UNCOV
49
    @classmethod
×
UNCOV
50
    def opt_out(cls, tgt: Target) -> bool:
×
UNCOV
51
        return tgt.get(SkipShellCommandPackageField).value
×
52

53

UNCOV
54
@rule(desc="Package with shell command", level=LogLevel.DEBUG)
×
UNCOV
55
async def package_shell_command(
×
56
    field_set: PackageShellCommandFieldSet,
57
) -> BuiltPackage:
58
    wrapped_tgt = await resolve_target(
×
59
        WrappedTargetRequest(field_set.address, description_of_origin="<infallible>"),
60
        **implicitly(),
61
    )
62
    target = wrapped_tgt.target
×
63

64
    shell_process = await prepare_process_request_from_target(
×
65
        ShellCommandProcessFromTargetRequest(target), **implicitly()
66
    )
67

68
    shell_process = dataclasses.replace(
×
69
        shell_process,
70
        cache_scope=shell_process.cache_scope or ProcessCacheScope.SUCCESSFUL,
71
    )
72

73
    result = await run_prepared_adhoc_process(**implicitly({shell_process: AdhocProcessRequest}))
×
74

75
    if result.process_result.exit_code != 0:
×
76
        raise ValueError(
×
77
            f"The `{target.alias}` at `{field_set.address}` failed with exit code {result.process_result.exit_code}.\n\n"
78
            f"stdout:\n\n{result.process_result.stdout.decode(errors='ignore')}\n\n"
79
            f"stderr:\n\n{result.process_result.stderr.decode(errors='ignore')}"
80
        )
81

82
    if result.adjusted_digest == EMPTY_DIGEST:
×
83
        raise ValueError(
×
84
            f"The `{target.alias}` at `{field_set.address}` did not produce or capture any output. "
85
            "The `package` goal is expected to produce output."
86
        )
87

88
    # Apply the output path for the artifacts.
89
    output_path = field_set.output_path.value_or_default(file_ending=None)
×
90
    output_digest: Digest
91
    if output_path:
×
92
        output_digest = await add_prefix(AddPrefix(result.adjusted_digest, output_path))
×
93
    else:
94
        output_digest = result.adjusted_digest
×
95

96
    output_digest_entries = await get_digest_entries(result.adjusted_digest)
×
97
    file_paths = sorted(e.path for e in output_digest_entries)
×
98
    artifacts = tuple(BuiltPackageArtifact(relpath=path) for path in file_paths)
×
99
    return BuiltPackage(output_digest, artifacts)
×
100

101

UNCOV
102
def rules():
×
UNCOV
103
    return (
×
104
        *collect_rules(),
105
        *shell_command.rules(),
106
        *adhoc_process_support_rules(),
107
        UnionRule(PackageFieldSet, PackageShellCommandFieldSet),
108
    )
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