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

UNCOV
4
from dataclasses import dataclass
×
UNCOV
5
from typing import Any
×
6

UNCOV
7
from pants.backend.shell.lint.shellcheck.skip_field import SkipShellcheckField
×
UNCOV
8
from pants.backend.shell.lint.shellcheck.subsystem import Shellcheck
×
UNCOV
9
from pants.backend.shell.target_types import ShellDependenciesField, ShellSourceField
×
UNCOV
10
from pants.core.goals.lint import LintResult, LintTargetsRequest
×
UNCOV
11
from pants.core.goals.resolves import ExportableTool
×
UNCOV
12
from pants.core.util_rules.config_files import find_config_file
×
UNCOV
13
from pants.core.util_rules.external_tool import download_external_tool
×
UNCOV
14
from pants.core.util_rules.partitions import PartitionerType
×
UNCOV
15
from pants.core.util_rules.source_files import SourceFilesRequest, determine_source_files
×
UNCOV
16
from pants.engine.fs import MergeDigests
×
UNCOV
17
from pants.engine.internals.graph import resolve_targets
×
UNCOV
18
from pants.engine.intrinsics import execute_process, merge_digests
×
UNCOV
19
from pants.engine.platform import Platform
×
UNCOV
20
from pants.engine.process import Process
×
UNCOV
21
from pants.engine.rules import collect_rules, concurrently, implicitly, rule
×
UNCOV
22
from pants.engine.target import DependenciesRequest, FieldSet, SourcesField, Target
×
UNCOV
23
from pants.engine.unions import UnionRule
×
UNCOV
24
from pants.util.logging import LogLevel
×
UNCOV
25
from pants.util.strutil import pluralize
×
26

27

UNCOV
28
@dataclass(frozen=True)
×
UNCOV
29
class ShellcheckFieldSet(FieldSet):
×
UNCOV
30
    required_fields = (ShellSourceField,)
×
31

32
    sources: ShellSourceField
33
    dependencies: ShellDependenciesField
34

UNCOV
35
    @classmethod
×
UNCOV
36
    def opt_out(cls, tgt: Target) -> bool:
×
37
        return tgt.get(SkipShellcheckField).value
×
38

39

UNCOV
40
class ShellcheckRequest(LintTargetsRequest):
×
UNCOV
41
    field_set_type = ShellcheckFieldSet
×
UNCOV
42
    tool_subsystem = Shellcheck  # type: ignore[assignment]
×
UNCOV
43
    partitioner_type = PartitionerType.DEFAULT_SINGLE_PARTITION
×
44

45

UNCOV
46
@rule(desc="Lint with Shellcheck", level=LogLevel.DEBUG)
×
UNCOV
47
async def run_shellcheck(
×
48
    request: ShellcheckRequest.Batch[ShellcheckFieldSet, Any],
49
    shellcheck: Shellcheck,
50
    platform: Platform,
51
) -> LintResult:
52
    # Shellcheck looks at direct dependencies to make sure that every symbol is defined, so we must
53
    # include those in the run.
54
    all_dependencies = await concurrently(
×
55
        resolve_targets(**implicitly(DependenciesRequest(field_set.dependencies)))
56
        for field_set in request.elements
57
    )
58
    direct_sources_get = determine_source_files(
×
59
        SourceFilesRequest(
60
            (field_set.sources for field_set in request.elements),
61
            for_sources_types=(ShellSourceField,),
62
            enable_codegen=True,
63
        )
64
    )
65
    dependency_sources_get = determine_source_files(
×
66
        SourceFilesRequest(
67
            (tgt.get(SourcesField) for dependencies in all_dependencies for tgt in dependencies),
68
            for_sources_types=(ShellSourceField,),
69
            enable_codegen=True,
70
        )
71
    )
72
    download_shellcheck_get = download_external_tool(shellcheck.get_request(platform))
×
73

74
    direct_sources, dependency_sources, downloaded_shellcheck = await concurrently(
×
75
        direct_sources_get, dependency_sources_get, download_shellcheck_get
76
    )
77
    config_files = await find_config_file(shellcheck.config_request(direct_sources.snapshot.dirs))
×
78
    input_digest = await merge_digests(
×
79
        MergeDigests(
80
            (
81
                direct_sources.snapshot.digest,
82
                dependency_sources.snapshot.digest,
83
                downloaded_shellcheck.digest,
84
                config_files.snapshot.digest,
85
            )
86
        )
87
    )
88

89
    process_result = await execute_process(
×
90
        Process(
91
            argv=[downloaded_shellcheck.exe, *shellcheck.args, *direct_sources.snapshot.files],
92
            input_digest=input_digest,
93
            description=f"Run Shellcheck on {pluralize(len(request.elements), 'file')}.",
94
            level=LogLevel.DEBUG,
95
        ),
96
        **implicitly(),
97
    )
98
    return LintResult.create(request, process_result)
×
99

100

UNCOV
101
def rules():
×
UNCOV
102
    return [
×
103
        *collect_rules(),
104
        *ShellcheckRequest.rules(),
105
        UnionRule(ExportableTool, Shellcheck),
106
    ]
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