• 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/python/lint/pylint/subsystem.py
1
# Copyright 2020 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 os.path
×
UNCOV
7
from collections.abc import Iterable
×
UNCOV
8
from dataclasses import dataclass
×
9

UNCOV
10
from pants.backend.python.lint.first_party_plugins import (
×
11
    BaseFirstPartyPlugins,
12
    resolve_first_party_plugins,
13
)
UNCOV
14
from pants.backend.python.lint.pylint.skip_field import SkipPylintField
×
UNCOV
15
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
×
UNCOV
16
from pants.backend.python.target_types import (
×
17
    ConsoleScript,
18
    InterpreterConstraintsField,
19
    PythonResolveField,
20
    PythonSourceField,
21
)
UNCOV
22
from pants.core.goals.resolves import ExportableTool
×
UNCOV
23
from pants.core.util_rules.config_files import ConfigFilesRequest
×
UNCOV
24
from pants.engine.addresses import UnparsedAddressInputs
×
UNCOV
25
from pants.engine.rules import collect_rules, rule
×
UNCOV
26
from pants.engine.target import FieldSet, Target
×
UNCOV
27
from pants.engine.unions import UnionRule
×
UNCOV
28
from pants.option.option_types import (
×
29
    ArgsListOption,
30
    BoolOption,
31
    FileOption,
32
    SkipOption,
33
    TargetListOption,
34
)
UNCOV
35
from pants.util.docutil import doc_url
×
UNCOV
36
from pants.util.logging import LogLevel
×
UNCOV
37
from pants.util.strutil import softwrap
×
38

39

UNCOV
40
@dataclass(frozen=True)
×
UNCOV
41
class PylintFieldSet(FieldSet):
×
UNCOV
42
    required_fields = (PythonSourceField,)
×
43

UNCOV
44
    source: PythonSourceField
×
UNCOV
45
    resolve: PythonResolveField
×
UNCOV
46
    interpreter_constraints: InterpreterConstraintsField
×
47

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

52

53
# --------------------------------------------------------------------------------------
54
# Subsystem
55
# --------------------------------------------------------------------------------------
56

57

UNCOV
58
class Pylint(PythonToolBase):
×
UNCOV
59
    options_scope = "pylint"
×
UNCOV
60
    name = "Pylint"
×
UNCOV
61
    help_short = "The Pylint linter for Python code (https://www.pylint.org/)."
×
62

UNCOV
63
    default_main = ConsoleScript("pylint")
×
UNCOV
64
    default_requirements = ["pylint>=2.13.0,<3"]
×
65

UNCOV
66
    default_lockfile_resource = ("pants.backend.python.lint.pylint", "pylint.lock")
×
67

UNCOV
68
    skip = SkipOption("lint")
×
UNCOV
69
    args = ArgsListOption(example="--ignore=foo.py,bar.py --disable=C0330,W0311")
×
UNCOV
70
    config = FileOption(
×
71
        default=None,
72
        advanced=True,
73
        help=lambda cls: softwrap(
74
            f"""
75
            Path to a config file understood by Pylint
76
            (http://pylint.pycqa.org/en/latest/user_guide/run.html#command-line-options).
77

78
            Setting this option will disable `[{cls.options_scope}].config_discovery`. Use
79
            this option if the config is located in a non-standard location.
80
            """
81
        ),
82
    )
UNCOV
83
    config_discovery = BoolOption(
×
84
        default=True,
85
        advanced=True,
86
        help=lambda cls: softwrap(
87
            f"""
88
            If true, Pants will include any relevant config files during
89
            runs (`.pylintrc`, `pylintrc`, `pyproject.toml`, and `setup.cfg`).
90

91
            Use `[{cls.options_scope}].config` instead if your config is in a
92
            non-standard location.
93
            """
94
        ),
95
    )
UNCOV
96
    _source_plugins = TargetListOption(
×
97
        advanced=True,
98
        help=softwrap(
99
            f"""
100
            An optional list of `python_sources` target addresses to load first-party plugins.
101

102
            You must set the plugin's parent directory as a source root. For
103
            example, if your plugin is at `build-support/pylint/custom_plugin.py`, add
104
            `'build-support/pylint'` to `[source].root_patterns` in `pants.toml`. This is
105
            necessary for Pants to know how to tell Pylint to discover your plugin. See
106
            {doc_url("docs/using-pants/key-concepts/source-roots")}
107

108
            You must also set `load-plugins=$module_name` in your Pylint config file.
109

110
            While your plugin's code can depend on other first-party code and third-party
111
            requirements, all first-party dependencies of the plugin must live in the same
112
            directory or a subdirectory.
113

114
            To instead load third-party plugins, add them to a custom resolve alongside
115
            pylint itself, as described in {doc_url("docs/python/overview/lockfiles#lockfiles-for-tools")}.
116
            """
117
        ),
118
    )
119

UNCOV
120
    def config_request(self, dirs: Iterable[str]) -> ConfigFilesRequest:
×
121
        # Refer to http://pylint.pycqa.org/en/latest/user_guide/run.html#command-line-options for
122
        # how config files are discovered.
123
        return ConfigFilesRequest(
×
124
            specified=self.config,
125
            specified_option_name=f"[{self.options_scope}].config",
126
            discovery=self.config_discovery,
127
            check_existence=[".pylintrc", *(os.path.join(d, "pylintrc") for d in ("", *dirs))],
128
            check_content={"pyproject.toml": b"[tool.pylint.", "setup.cfg": b"[pylint."},
129
        )
130

UNCOV
131
    @property
×
UNCOV
132
    def source_plugins(self) -> UnparsedAddressInputs:
×
133
        return UnparsedAddressInputs(
×
134
            self._source_plugins,
135
            owning_address=None,
136
            description_of_origin=f"the option `[{self.options_scope}].source_plugins`",
137
        )
138

139

140
# --------------------------------------------------------------------------------------
141
# First-party plugins
142
# --------------------------------------------------------------------------------------
143

144

UNCOV
145
class PylintFirstPartyPlugins(BaseFirstPartyPlugins):
×
UNCOV
146
    pass
×
147

148

UNCOV
149
@rule(desc="Prepare [pylint].source_plugins", level=LogLevel.DEBUG)
×
UNCOV
150
async def pylint_first_party_plugins(pylint: Pylint) -> PylintFirstPartyPlugins:
×
151
    return await resolve_first_party_plugins(pylint.source_plugins, PylintFirstPartyPlugins)
×
152

153

UNCOV
154
def rules():
×
UNCOV
155
    return (
×
156
        *collect_rules(),
157
        UnionRule(ExportableTool, Pylint),
158
    )
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