We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Using a newer version of `pylint`
I'm trying to use a newer version of `pylint` with Pants. Even though I've got `pylint` set to version 2.8.2 in `requirements.txt`/`poetry.lock`, it seems that it kept getting built with version `>=2.4.4,<2.5`. After looking around [in the docs](https://www.pantsbuild.org/v2.0/docs/reference-pylint#advanced-options), I discovered that that's the default `pylint` version in Pants. There's apparently an option to set an alternative `version` in `pants.toml`, which I'm able to use to lint my codebase using a more recent version of `pylint`.

However, I'd like to understand:
1. Why does Pants have a default version of `pylint` at all instead of always using the most recent version (or the version specified in e.g. `requirements.txt`)?
2. Related to the previous question: what, if any, are the risks of using a newer `pylint` version in Pants?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/python/pants/backend/python/lint/pylint/subsystem.py`
Content:
```
1 # Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).
2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
3 
4 from __future__ import annotations
5 
6 import os.path
7 from typing import Iterable, cast
8 
9 from pants.backend.python.subsystems.python_tool_base import PythonToolBase
10 from pants.backend.python.target_types import ConsoleScript
11 from pants.core.util_rules.config_files import ConfigFilesRequest
12 from pants.engine.addresses import UnparsedAddressInputs
13 from pants.option.custom_types import file_option, shell_str, target_option
14 from pants.util.docutil import bracketed_docs_url
15 
16 
17 class Pylint(PythonToolBase):
18     options_scope = "pylint"
19     help = "The Pylint linter for Python code (https://www.pylint.org/)."
20 
21     default_version = "pylint>=2.4.4,<2.5"
22     default_main = ConsoleScript("pylint")
23 
24     @classmethod
25     def register_options(cls, register):
26         super().register_options(register)
27         register(
28             "--skip",
29             type=bool,
30             default=False,
31             help=f"Don't use Pylint when running `{register.bootstrap.pants_bin_name} lint`",
32         )
33         register(
34             "--args",
35             type=list,
36             member_type=shell_str,
37             help=(
38                 "Arguments to pass directly to Pylint, e.g. "
39                 f'`--{cls.options_scope}-args="--ignore=foo.py,bar.py --disable=C0330,W0311"`'
40             ),
41         )
42         register(
43             "--config",
44             type=file_option,
45             default=None,
46             advanced=True,
47             help=(
48                 "Path to a config file understood by Pylint "
49                 "(http://pylint.pycqa.org/en/latest/user_guide/run.html#command-line-options).\n\n"
50                 f"Setting this option will disable `[{cls.options_scope}].config_discovery`. Use "
51                 f"this option if the config is located in a non-standard location."
52             ),
53         )
54         register(
55             "--config-discovery",
56             type=bool,
57             default=True,
58             advanced=True,
59             help=(
60                 "If true, Pants will include any relevant config files during "
61                 "runs (`.pylintrc`, `pylintrc`, `pyproject.toml`, and `setup.cfg`)."
62                 f"\n\nUse `[{cls.options_scope}].config` instead if your config is in a "
63                 f"non-standard location."
64             ),
65         )
66         register(
67             "--source-plugins",
68             type=list,
69             member_type=target_option,
70             advanced=True,
71             help=(
72                 "An optional list of `python_library` target addresses to load first-party "
73                 "plugins.\n\nYou must set the plugin's parent directory as a source root. For "
74                 "example, if your plugin is at `build-support/pylint/custom_plugin.py`, add "
75                 "'build-support/pylint' to `[source].root_patterns` in `pants.toml`. This is "
76                 "necessary for Pants to know how to tell Pylint to discover your plugin. See "
77                 f"{bracketed_docs_url('source-roots')}\n\nYou must also set `load-plugins=$module_name` in "
78                 "your Pylint config file, and set the `[pylint].config` option in `pants.toml`."
79                 "\n\nWhile your plugin's code can depend on other first-party code and third-party "
80                 "requirements, all first-party dependencies of the plugin must live in the same "
81                 "directory or a subdirectory.\n\nTo instead load third-party plugins, set the "
82                 "option `[pylint].extra_requirements` and set the `load-plugins` option in your "
83                 "Pylint config."
84             ),
85         )
86 
87     @property
88     def skip(self) -> bool:
89         return cast(bool, self.options.skip)
90 
91     @property
92     def args(self) -> tuple[str, ...]:
93         return tuple(self.options.args)
94 
95     @property
96     def config(self) -> str | None:
97         return cast("str | None", self.options.config)
98 
99     def config_request(self, dirs: Iterable[str]) -> ConfigFilesRequest:
100         # Refer to http://pylint.pycqa.org/en/latest/user_guide/run.html#command-line-options for
101         # how config files are discovered.
102         return ConfigFilesRequest(
103             specified=self.config,
104             specified_option_name=f"[{self.options_scope}].config",
105             discovery=cast(bool, self.options.config_discovery),
106             check_existence=[".pylinrc", *(os.path.join(d, "pylintrc") for d in ("", *dirs))],
107             check_content={"pyproject.toml": b"[tool.pylint]", "setup.cfg": b"[pylint."},
108         )
109 
110     @property
111     def source_plugins(self) -> UnparsedAddressInputs:
112         return UnparsedAddressInputs(self.options.source_plugins, owning_address=None)
113
```

Path: `src/python/pants/backend/python/lint/bandit/subsystem.py`
Content:
```
1 # Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).
2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
3 
4 from __future__ import annotations
5 
6 from typing import cast
7 
8 from pants.backend.python.subsystems.python_tool_base import PythonToolBase
9 from pants.backend.python.target_types import ConsoleScript
10 from pants.core.util_rules.config_files import ConfigFilesRequest
11 from pants.option.custom_types import file_option, shell_str
12 
13 
14 class Bandit(PythonToolBase):
15     options_scope = "bandit"
16     help = "A tool for finding security issues in Python code (https://bandit.readthedocs.io)."
17 
18     default_version = "bandit>=1.6.2,<1.7"
19     default_extra_requirements = [
20         "setuptools<45; python_full_version == '2.7.*'",
21         "setuptools; python_version > '2.7'",
22         "stevedore<3",  # stevedore 3.0 breaks Bandit.
23     ]
24     default_main = ConsoleScript("bandit")
25 
26     @classmethod
27     def register_options(cls, register):
28         super().register_options(register)
29         register(
30             "--skip",
31             type=bool,
32             default=False,
33             help=f"Don't use Bandit when running `{register.bootstrap.pants_bin_name} lint`",
34         )
35         register(
36             "--args",
37             type=list,
38             member_type=shell_str,
39             help=(
40                 f"Arguments to pass directly to Bandit, e.g. "
41                 f'`--{cls.options_scope}-args="--skip B101,B308 --confidence"`'
42             ),
43         )
44         register(
45             "--config",
46             type=file_option,
47             default=None,
48             advanced=True,
49             help=(
50                 "Path to a Bandit YAML config file "
51                 "(https://bandit.readthedocs.io/en/latest/config.html)."
52             ),
53         )
54 
55     @property
56     def skip(self) -> bool:
57         return cast(bool, self.options.skip)
58 
59     @property
60     def args(self) -> tuple[str, ...]:
61         return tuple(self.options.args)
62 
63     @property
64     def config(self) -> str | None:
65         return cast("str | None", self.options.config)
66 
67     @property
68     def config_request(self) -> ConfigFilesRequest:
69         # Refer to https://bandit.readthedocs.io/en/latest/config.html. Note that there are no
70         # default locations for Bandit config files.
71         return ConfigFilesRequest(
72             specified=self.config, specified_option_name=f"{self.options_scope}.config"
73         )
74
```

Path: `src/python/pants/backend/python/lint/black/subsystem.py`
Content:
```
1 # Copyright 2019 Pants project contributors (see CONTRIBUTORS.md).
2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
3 
4 from __future__ import annotations
5 
6 import os.path
7 from typing import Iterable, cast
8 
9 from pants.backend.python.subsystems.python_tool_base import PythonToolBase
10 from pants.backend.python.target_types import ConsoleScript
11 from pants.core.util_rules.config_files import ConfigFilesRequest
12 from pants.option.custom_types import file_option, shell_str
13 
14 
15 class Black(PythonToolBase):
16     options_scope = "black"
17     help = "The Black Python code formatter (https://black.readthedocs.io/)."
18 
19     # TODO: simplify `test_works_with_python39()` to stop using a VCS version.
20     default_version = "black==20.8b1"
21     default_extra_requirements = ["setuptools"]
22     default_main = ConsoleScript("black")
23     register_interpreter_constraints = True
24     default_interpreter_constraints = ["CPython>=3.6"]
25 
26     @classmethod
27     def register_options(cls, register):
28         super().register_options(register)
29         register(
30             "--skip",
31             type=bool,
32             default=False,
33             help=(
34                 f"Don't use Black when running `{register.bootstrap.pants_bin_name} fmt` and "
35                 f"`{register.bootstrap.pants_bin_name} lint`"
36             ),
37         )
38         register(
39             "--args",
40             type=list,
41             member_type=shell_str,
42             help=(
43                 "Arguments to pass directly to Black, e.g. "
44                 f'`--{cls.options_scope}-args="--target-version=py37 --quiet"`'
45             ),
46         )
47         register(
48             "--config",
49             type=file_option,
50             default=None,
51             advanced=True,
52             help=(
53                 "Path to a TOML config file understood by Black "
54                 "(https://github.com/psf/black#configuration-format).\n\n"
55                 f"Setting this option will disable `[{cls.options_scope}].config_discovery`. Use "
56                 f"this option if the config is located in a non-standard location."
57             ),
58         )
59         register(
60             "--config-discovery",
61             type=bool,
62             default=True,
63             advanced=True,
64             help=(
65                 "If true, Pants will include any relevant pyproject.toml config files during runs."
66                 f"\n\nUse `[{cls.options_scope}].config` instead if your config is in a "
67                 f"non-standard location."
68             ),
69         )
70 
71     @property
72     def skip(self) -> bool:
73         return cast(bool, self.options.skip)
74 
75     @property
76     def args(self) -> tuple[str, ...]:
77         return tuple(self.options.args)
78 
79     @property
80     def config(self) -> str | None:
81         return cast("str | None", self.options.config)
82 
83     def config_request(self, dirs: Iterable[str]) -> ConfigFilesRequest:
84         # Refer to https://github.com/psf/black#where-black-looks-for-the-file for how Black
85         # discovers config.
86         candidates = {os.path.join(d, "pyproject.toml"): b"[tool.black]" for d in ("", *dirs)}
87         return ConfigFilesRequest(
88             specified=self.config,
89             specified_option_name=f"[{self.options_scope}].config",
90             discovery=cast(bool, self.options.config_discovery),
91             check_content=candidates,
92         )
93
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/python/pants/backend/python/lint/bandit/subsystem.py b/src/python/pants/backend/python/lint/bandit/subsystem.py
--- a/src/python/pants/backend/python/lint/bandit/subsystem.py
+++ b/src/python/pants/backend/python/lint/bandit/subsystem.py
@@ -15,7 +15,7 @@
     options_scope = "bandit"
     help = "A tool for finding security issues in Python code (https://bandit.readthedocs.io)."
 
-    default_version = "bandit>=1.6.2,<1.7"
+    default_version = "bandit>=1.7.0,<1.8"
     default_extra_requirements = [
         "setuptools<45; python_full_version == '2.7.*'",
         "setuptools; python_version > '2.7'",
diff --git a/src/python/pants/backend/python/lint/black/subsystem.py b/src/python/pants/backend/python/lint/black/subsystem.py
--- a/src/python/pants/backend/python/lint/black/subsystem.py
+++ b/src/python/pants/backend/python/lint/black/subsystem.py
@@ -17,7 +17,7 @@
     help = "The Black Python code formatter (https://black.readthedocs.io/)."
 
     # TODO: simplify `test_works_with_python39()` to stop using a VCS version.
-    default_version = "black==20.8b1"
+    default_version = "black==21.5b2"
     default_extra_requirements = ["setuptools"]
     default_main = ConsoleScript("black")
     register_interpreter_constraints = True
diff --git a/src/python/pants/backend/python/lint/pylint/subsystem.py b/src/python/pants/backend/python/lint/pylint/subsystem.py
--- a/src/python/pants/backend/python/lint/pylint/subsystem.py
+++ b/src/python/pants/backend/python/lint/pylint/subsystem.py
@@ -18,7 +18,7 @@
     options_scope = "pylint"
     help = "The Pylint linter for Python code (https://www.pylint.org/)."
 
-    default_version = "pylint>=2.4.4,<2.5"
+    default_version = "pylint>=2.6.2,<2.7"
     default_main = ConsoleScript("pylint")
 
     @classmethod

{"golden_diff": "diff --git a/src/python/pants/backend/python/lint/bandit/subsystem.py b/src/python/pants/backend/python/lint/bandit/subsystem.py\n--- a/src/python/pants/backend/python/lint/bandit/subsystem.py\n+++ b/src/python/pants/backend/python/lint/bandit/subsystem.py\n@@ -15,7 +15,7 @@\n     options_scope = \"bandit\"\n     help = \"A tool for finding security issues in Python code (https://bandit.readthedocs.io).\"\n \n-    default_version = \"bandit>=1.6.2,<1.7\"\n+    default_version = \"bandit>=1.7.0,<1.8\"\n     default_extra_requirements = [\n         \"setuptools<45; python_full_version == '2.7.*'\",\n         \"setuptools; python_version > '2.7'\",\ndiff --git a/src/python/pants/backend/python/lint/black/subsystem.py b/src/python/pants/backend/python/lint/black/subsystem.py\n--- a/src/python/pants/backend/python/lint/black/subsystem.py\n+++ b/src/python/pants/backend/python/lint/black/subsystem.py\n@@ -17,7 +17,7 @@\n     help = \"The Black Python code formatter (https://black.readthedocs.io/).\"\n \n     # TODO: simplify `test_works_with_python39()` to stop using a VCS version.\n-    default_version = \"black==20.8b1\"\n+    default_version = \"black==21.5b2\"\n     default_extra_requirements = [\"setuptools\"]\n     default_main = ConsoleScript(\"black\")\n     register_interpreter_constraints = True\ndiff --git a/src/python/pants/backend/python/lint/pylint/subsystem.py b/src/python/pants/backend/python/lint/pylint/subsystem.py\n--- a/src/python/pants/backend/python/lint/pylint/subsystem.py\n+++ b/src/python/pants/backend/python/lint/pylint/subsystem.py\n@@ -18,7 +18,7 @@\n     options_scope = \"pylint\"\n     help = \"The Pylint linter for Python code (https://www.pylint.org/).\"\n \n-    default_version = \"pylint>=2.4.4,<2.5\"\n+    default_version = \"pylint>=2.6.2,<2.7\"\n     default_main = ConsoleScript(\"pylint\")\n \n     @classmethod\n", "issue": "Using a newer version of `pylint`\nI'm trying to use a newer version of `pylint` with Pants. Even though I've got `pylint` set to version 2.8.2 in `requirements.txt`/`poetry.lock`, it seems that it kept getting built with version `>=2.4.4,<2.5`. After looking around [in the docs](https://www.pantsbuild.org/v2.0/docs/reference-pylint#advanced-options), I discovered that that's the default `pylint` version in Pants. There's apparently an option to set an alternative `version` in `pants.toml`, which I'm able to use to lint my codebase using a more recent version of `pylint`.\r\n\r\nHowever, I'd like to understand:\r\n1. Why does Pants have a default version of `pylint` at all instead of always using the most recent version (or the version specified in e.g. `requirements.txt`)?\r\n2. Related to the previous question: what, if any, are the risks of using a newer `pylint` version in Pants?\n", "before_files": [{"content": "# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import annotations\n\nimport os.path\nfrom typing import Iterable, cast\n\nfrom pants.backend.python.subsystems.python_tool_base import PythonToolBase\nfrom pants.backend.python.target_types import ConsoleScript\nfrom pants.core.util_rules.config_files import ConfigFilesRequest\nfrom pants.engine.addresses import UnparsedAddressInputs\nfrom pants.option.custom_types import file_option, shell_str, target_option\nfrom pants.util.docutil import bracketed_docs_url\n\n\nclass Pylint(PythonToolBase):\n    options_scope = \"pylint\"\n    help = \"The Pylint linter for Python code (https://www.pylint.org/).\"\n\n    default_version = \"pylint>=2.4.4,<2.5\"\n    default_main = ConsoleScript(\"pylint\")\n\n    @classmethod\n    def register_options(cls, register):\n        super().register_options(register)\n        register(\n            \"--skip\",\n            type=bool,\n            default=False,\n            help=f\"Don't use Pylint when running `{register.bootstrap.pants_bin_name} lint`\",\n        )\n        register(\n            \"--args\",\n            type=list,\n            member_type=shell_str,\n            help=(\n                \"Arguments to pass directly to Pylint, e.g. \"\n                f'`--{cls.options_scope}-args=\"--ignore=foo.py,bar.py --disable=C0330,W0311\"`'\n            ),\n        )\n        register(\n            \"--config\",\n            type=file_option,\n            default=None,\n            advanced=True,\n            help=(\n                \"Path to a config file understood by Pylint \"\n                \"(http://pylint.pycqa.org/en/latest/user_guide/run.html#command-line-options).\\n\\n\"\n                f\"Setting this option will disable `[{cls.options_scope}].config_discovery`. Use \"\n                f\"this option if the config is located in a non-standard location.\"\n            ),\n        )\n        register(\n            \"--config-discovery\",\n            type=bool,\n            default=True,\n            advanced=True,\n            help=(\n                \"If true, Pants will include any relevant config files during \"\n                \"runs (`.pylintrc`, `pylintrc`, `pyproject.toml`, and `setup.cfg`).\"\n                f\"\\n\\nUse `[{cls.options_scope}].config` instead if your config is in a \"\n                f\"non-standard location.\"\n            ),\n        )\n        register(\n            \"--source-plugins\",\n            type=list,\n            member_type=target_option,\n            advanced=True,\n            help=(\n                \"An optional list of `python_library` target addresses to load first-party \"\n                \"plugins.\\n\\nYou must set the plugin's parent directory as a source root. For \"\n                \"example, if your plugin is at `build-support/pylint/custom_plugin.py`, add \"\n                \"'build-support/pylint' to `[source].root_patterns` in `pants.toml`. This is \"\n                \"necessary for Pants to know how to tell Pylint to discover your plugin. See \"\n                f\"{bracketed_docs_url('source-roots')}\\n\\nYou must also set `load-plugins=$module_name` in \"\n                \"your Pylint config file, and set the `[pylint].config` option in `pants.toml`.\"\n                \"\\n\\nWhile your plugin's code can depend on other first-party code and third-party \"\n                \"requirements, all first-party dependencies of the plugin must live in the same \"\n                \"directory or a subdirectory.\\n\\nTo instead load third-party plugins, set the \"\n                \"option `[pylint].extra_requirements` and set the `load-plugins` option in your \"\n                \"Pylint config.\"\n            ),\n        )\n\n    @property\n    def skip(self) -> bool:\n        return cast(bool, self.options.skip)\n\n    @property\n    def args(self) -> tuple[str, ...]:\n        return tuple(self.options.args)\n\n    @property\n    def config(self) -> str | None:\n        return cast(\"str | None\", self.options.config)\n\n    def config_request(self, dirs: Iterable[str]) -> ConfigFilesRequest:\n        # Refer to http://pylint.pycqa.org/en/latest/user_guide/run.html#command-line-options for\n        # how config files are discovered.\n        return ConfigFilesRequest(\n            specified=self.config,\n            specified_option_name=f\"[{self.options_scope}].config\",\n            discovery=cast(bool, self.options.config_discovery),\n            check_existence=[\".pylinrc\", *(os.path.join(d, \"pylintrc\") for d in (\"\", *dirs))],\n            check_content={\"pyproject.toml\": b\"[tool.pylint]\", \"setup.cfg\": b\"[pylint.\"},\n        )\n\n    @property\n    def source_plugins(self) -> UnparsedAddressInputs:\n        return UnparsedAddressInputs(self.options.source_plugins, owning_address=None)\n", "path": "src/python/pants/backend/python/lint/pylint/subsystem.py"}, {"content": "# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import annotations\n\nfrom typing import cast\n\nfrom pants.backend.python.subsystems.python_tool_base import PythonToolBase\nfrom pants.backend.python.target_types import ConsoleScript\nfrom pants.core.util_rules.config_files import ConfigFilesRequest\nfrom pants.option.custom_types import file_option, shell_str\n\n\nclass Bandit(PythonToolBase):\n    options_scope = \"bandit\"\n    help = \"A tool for finding security issues in Python code (https://bandit.readthedocs.io).\"\n\n    default_version = \"bandit>=1.6.2,<1.7\"\n    default_extra_requirements = [\n        \"setuptools<45; python_full_version == '2.7.*'\",\n        \"setuptools; python_version > '2.7'\",\n        \"stevedore<3\",  # stevedore 3.0 breaks Bandit.\n    ]\n    default_main = ConsoleScript(\"bandit\")\n\n    @classmethod\n    def register_options(cls, register):\n        super().register_options(register)\n        register(\n            \"--skip\",\n            type=bool,\n            default=False,\n            help=f\"Don't use Bandit when running `{register.bootstrap.pants_bin_name} lint`\",\n        )\n        register(\n            \"--args\",\n            type=list,\n            member_type=shell_str,\n            help=(\n                f\"Arguments to pass directly to Bandit, e.g. \"\n                f'`--{cls.options_scope}-args=\"--skip B101,B308 --confidence\"`'\n            ),\n        )\n        register(\n            \"--config\",\n            type=file_option,\n            default=None,\n            advanced=True,\n            help=(\n                \"Path to a Bandit YAML config file \"\n                \"(https://bandit.readthedocs.io/en/latest/config.html).\"\n            ),\n        )\n\n    @property\n    def skip(self) -> bool:\n        return cast(bool, self.options.skip)\n\n    @property\n    def args(self) -> tuple[str, ...]:\n        return tuple(self.options.args)\n\n    @property\n    def config(self) -> str | None:\n        return cast(\"str | None\", self.options.config)\n\n    @property\n    def config_request(self) -> ConfigFilesRequest:\n        # Refer to https://bandit.readthedocs.io/en/latest/config.html. Note that there are no\n        # default locations for Bandit config files.\n        return ConfigFilesRequest(\n            specified=self.config, specified_option_name=f\"{self.options_scope}.config\"\n        )\n", "path": "src/python/pants/backend/python/lint/bandit/subsystem.py"}, {"content": "# Copyright 2019 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import annotations\n\nimport os.path\nfrom typing import Iterable, cast\n\nfrom pants.backend.python.subsystems.python_tool_base import PythonToolBase\nfrom pants.backend.python.target_types import ConsoleScript\nfrom pants.core.util_rules.config_files import ConfigFilesRequest\nfrom pants.option.custom_types import file_option, shell_str\n\n\nclass Black(PythonToolBase):\n    options_scope = \"black\"\n    help = \"The Black Python code formatter (https://black.readthedocs.io/).\"\n\n    # TODO: simplify `test_works_with_python39()` to stop using a VCS version.\n    default_version = \"black==20.8b1\"\n    default_extra_requirements = [\"setuptools\"]\n    default_main = ConsoleScript(\"black\")\n    register_interpreter_constraints = True\n    default_interpreter_constraints = [\"CPython>=3.6\"]\n\n    @classmethod\n    def register_options(cls, register):\n        super().register_options(register)\n        register(\n            \"--skip\",\n            type=bool,\n            default=False,\n            help=(\n                f\"Don't use Black when running `{register.bootstrap.pants_bin_name} fmt` and \"\n                f\"`{register.bootstrap.pants_bin_name} lint`\"\n            ),\n        )\n        register(\n            \"--args\",\n            type=list,\n            member_type=shell_str,\n            help=(\n                \"Arguments to pass directly to Black, e.g. \"\n                f'`--{cls.options_scope}-args=\"--target-version=py37 --quiet\"`'\n            ),\n        )\n        register(\n            \"--config\",\n            type=file_option,\n            default=None,\n            advanced=True,\n            help=(\n                \"Path to a TOML config file understood by Black \"\n                \"(https://github.com/psf/black#configuration-format).\\n\\n\"\n                f\"Setting this option will disable `[{cls.options_scope}].config_discovery`. Use \"\n                f\"this option if the config is located in a non-standard location.\"\n            ),\n        )\n        register(\n            \"--config-discovery\",\n            type=bool,\n            default=True,\n            advanced=True,\n            help=(\n                \"If true, Pants will include any relevant pyproject.toml config files during runs.\"\n                f\"\\n\\nUse `[{cls.options_scope}].config` instead if your config is in a \"\n                f\"non-standard location.\"\n            ),\n        )\n\n    @property\n    def skip(self) -> bool:\n        return cast(bool, self.options.skip)\n\n    @property\n    def args(self) -> tuple[str, ...]:\n        return tuple(self.options.args)\n\n    @property\n    def config(self) -> str | None:\n        return cast(\"str | None\", self.options.config)\n\n    def config_request(self, dirs: Iterable[str]) -> ConfigFilesRequest:\n        # Refer to https://github.com/psf/black#where-black-looks-for-the-file for how Black\n        # discovers config.\n        candidates = {os.path.join(d, \"pyproject.toml\"): b\"[tool.black]\" for d in (\"\", *dirs)}\n        return ConfigFilesRequest(\n            specified=self.config,\n            specified_option_name=f\"[{self.options_scope}].config\",\n            discovery=cast(bool, self.options.config_discovery),\n            check_content=candidates,\n        )\n", "path": "src/python/pants/backend/python/lint/black/subsystem.py"}], "after_files": [{"content": "# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import annotations\n\nimport os.path\nfrom typing import Iterable, cast\n\nfrom pants.backend.python.subsystems.python_tool_base import PythonToolBase\nfrom pants.backend.python.target_types import ConsoleScript\nfrom pants.core.util_rules.config_files import ConfigFilesRequest\nfrom pants.engine.addresses import UnparsedAddressInputs\nfrom pants.option.custom_types import file_option, shell_str, target_option\nfrom pants.util.docutil import bracketed_docs_url\n\n\nclass Pylint(PythonToolBase):\n    options_scope = \"pylint\"\n    help = \"The Pylint linter for Python code (https://www.pylint.org/).\"\n\n    default_version = \"pylint>=2.6.2,<2.7\"\n    default_main = ConsoleScript(\"pylint\")\n\n    @classmethod\n    def register_options(cls, register):\n        super().register_options(register)\n        register(\n            \"--skip\",\n            type=bool,\n            default=False,\n            help=f\"Don't use Pylint when running `{register.bootstrap.pants_bin_name} lint`\",\n        )\n        register(\n            \"--args\",\n            type=list,\n            member_type=shell_str,\n            help=(\n                \"Arguments to pass directly to Pylint, e.g. \"\n                f'`--{cls.options_scope}-args=\"--ignore=foo.py,bar.py --disable=C0330,W0311\"`'\n            ),\n        )\n        register(\n            \"--config\",\n            type=file_option,\n            default=None,\n            advanced=True,\n            help=(\n                \"Path to a config file understood by Pylint \"\n                \"(http://pylint.pycqa.org/en/latest/user_guide/run.html#command-line-options).\\n\\n\"\n                f\"Setting this option will disable `[{cls.options_scope}].config_discovery`. Use \"\n                f\"this option if the config is located in a non-standard location.\"\n            ),\n        )\n        register(\n            \"--config-discovery\",\n            type=bool,\n            default=True,\n            advanced=True,\n            help=(\n                \"If true, Pants will include any relevant config files during \"\n                \"runs (`.pylintrc`, `pylintrc`, `pyproject.toml`, and `setup.cfg`).\"\n                f\"\\n\\nUse `[{cls.options_scope}].config` instead if your config is in a \"\n                f\"non-standard location.\"\n            ),\n        )\n        register(\n            \"--source-plugins\",\n            type=list,\n            member_type=target_option,\n            advanced=True,\n            help=(\n                \"An optional list of `python_library` target addresses to load first-party \"\n                \"plugins.\\n\\nYou must set the plugin's parent directory as a source root. For \"\n                \"example, if your plugin is at `build-support/pylint/custom_plugin.py`, add \"\n                \"'build-support/pylint' to `[source].root_patterns` in `pants.toml`. This is \"\n                \"necessary for Pants to know how to tell Pylint to discover your plugin. See \"\n                f\"{bracketed_docs_url('source-roots')}\\n\\nYou must also set `load-plugins=$module_name` in \"\n                \"your Pylint config file, and set the `[pylint].config` option in `pants.toml`.\"\n                \"\\n\\nWhile your plugin's code can depend on other first-party code and third-party \"\n                \"requirements, all first-party dependencies of the plugin must live in the same \"\n                \"directory or a subdirectory.\\n\\nTo instead load third-party plugins, set the \"\n                \"option `[pylint].extra_requirements` and set the `load-plugins` option in your \"\n                \"Pylint config.\"\n            ),\n        )\n\n    @property\n    def skip(self) -> bool:\n        return cast(bool, self.options.skip)\n\n    @property\n    def args(self) -> tuple[str, ...]:\n        return tuple(self.options.args)\n\n    @property\n    def config(self) -> str | None:\n        return cast(\"str | None\", self.options.config)\n\n    def config_request(self, dirs: Iterable[str]) -> ConfigFilesRequest:\n        # Refer to http://pylint.pycqa.org/en/latest/user_guide/run.html#command-line-options for\n        # how config files are discovered.\n        return ConfigFilesRequest(\n            specified=self.config,\n            specified_option_name=f\"[{self.options_scope}].config\",\n            discovery=cast(bool, self.options.config_discovery),\n            check_existence=[\".pylinrc\", *(os.path.join(d, \"pylintrc\") for d in (\"\", *dirs))],\n            check_content={\"pyproject.toml\": b\"[tool.pylint]\", \"setup.cfg\": b\"[pylint.\"},\n        )\n\n    @property\n    def source_plugins(self) -> UnparsedAddressInputs:\n        return UnparsedAddressInputs(self.options.source_plugins, owning_address=None)\n", "path": "src/python/pants/backend/python/lint/pylint/subsystem.py"}, {"content": "# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import annotations\n\nfrom typing import cast\n\nfrom pants.backend.python.subsystems.python_tool_base import PythonToolBase\nfrom pants.backend.python.target_types import ConsoleScript\nfrom pants.core.util_rules.config_files import ConfigFilesRequest\nfrom pants.option.custom_types import file_option, shell_str\n\n\nclass Bandit(PythonToolBase):\n    options_scope = \"bandit\"\n    help = \"A tool for finding security issues in Python code (https://bandit.readthedocs.io).\"\n\n    default_version = \"bandit>=1.7.0,<1.8\"\n    default_extra_requirements = [\n        \"setuptools<45; python_full_version == '2.7.*'\",\n        \"setuptools; python_version > '2.7'\",\n        \"stevedore<3\",  # stevedore 3.0 breaks Bandit.\n    ]\n    default_main = ConsoleScript(\"bandit\")\n\n    @classmethod\n    def register_options(cls, register):\n        super().register_options(register)\n        register(\n            \"--skip\",\n            type=bool,\n            default=False,\n            help=f\"Don't use Bandit when running `{register.bootstrap.pants_bin_name} lint`\",\n        )\n        register(\n            \"--args\",\n            type=list,\n            member_type=shell_str,\n            help=(\n                f\"Arguments to pass directly to Bandit, e.g. \"\n                f'`--{cls.options_scope}-args=\"--skip B101,B308 --confidence\"`'\n            ),\n        )\n        register(\n            \"--config\",\n            type=file_option,\n            default=None,\n            advanced=True,\n            help=(\n                \"Path to a Bandit YAML config file \"\n                \"(https://bandit.readthedocs.io/en/latest/config.html).\"\n            ),\n        )\n\n    @property\n    def skip(self) -> bool:\n        return cast(bool, self.options.skip)\n\n    @property\n    def args(self) -> tuple[str, ...]:\n        return tuple(self.options.args)\n\n    @property\n    def config(self) -> str | None:\n        return cast(\"str | None\", self.options.config)\n\n    @property\n    def config_request(self) -> ConfigFilesRequest:\n        # Refer to https://bandit.readthedocs.io/en/latest/config.html. Note that there are no\n        # default locations for Bandit config files.\n        return ConfigFilesRequest(\n            specified=self.config, specified_option_name=f\"{self.options_scope}.config\"\n        )\n", "path": "src/python/pants/backend/python/lint/bandit/subsystem.py"}, {"content": "# Copyright 2019 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import annotations\n\nimport os.path\nfrom typing import Iterable, cast\n\nfrom pants.backend.python.subsystems.python_tool_base import PythonToolBase\nfrom pants.backend.python.target_types import ConsoleScript\nfrom pants.core.util_rules.config_files import ConfigFilesRequest\nfrom pants.option.custom_types import file_option, shell_str\n\n\nclass Black(PythonToolBase):\n    options_scope = \"black\"\n    help = \"The Black Python code formatter (https://black.readthedocs.io/).\"\n\n    # TODO: simplify `test_works_with_python39()` to stop using a VCS version.\n    default_version = \"black==21.5b2\"\n    default_extra_requirements = [\"setuptools\"]\n    default_main = ConsoleScript(\"black\")\n    register_interpreter_constraints = True\n    default_interpreter_constraints = [\"CPython>=3.6\"]\n\n    @classmethod\n    def register_options(cls, register):\n        super().register_options(register)\n        register(\n            \"--skip\",\n            type=bool,\n            default=False,\n            help=(\n                f\"Don't use Black when running `{register.bootstrap.pants_bin_name} fmt` and \"\n                f\"`{register.bootstrap.pants_bin_name} lint`\"\n            ),\n        )\n        register(\n            \"--args\",\n            type=list,\n            member_type=shell_str,\n            help=(\n                \"Arguments to pass directly to Black, e.g. \"\n                f'`--{cls.options_scope}-args=\"--target-version=py37 --quiet\"`'\n            ),\n        )\n        register(\n            \"--config\",\n            type=file_option,\n            default=None,\n            advanced=True,\n            help=(\n                \"Path to a TOML config file understood by Black \"\n                \"(https://github.com/psf/black#configuration-format).\\n\\n\"\n                f\"Setting this option will disable `[{cls.options_scope}].config_discovery`. Use \"\n                f\"this option if the config is located in a non-standard location.\"\n            ),\n        )\n        register(\n            \"--config-discovery\",\n            type=bool,\n            default=True,\n            advanced=True,\n            help=(\n                \"If true, Pants will include any relevant pyproject.toml config files during runs.\"\n                f\"\\n\\nUse `[{cls.options_scope}].config` instead if your config is in a \"\n                f\"non-standard location.\"\n            ),\n        )\n\n    @property\n    def skip(self) -> bool:\n        return cast(bool, self.options.skip)\n\n    @property\n    def args(self) -> tuple[str, ...]:\n        return tuple(self.options.args)\n\n    @property\n    def config(self) -> str | None:\n        return cast(\"str | None\", self.options.config)\n\n    def config_request(self, dirs: Iterable[str]) -> ConfigFilesRequest:\n        # Refer to https://github.com/psf/black#where-black-looks-for-the-file for how Black\n        # discovers config.\n        candidates = {os.path.join(d, \"pyproject.toml\"): b\"[tool.black]\" for d in (\"\", *dirs)}\n        return ConfigFilesRequest(\n            specified=self.config,\n            specified_option_name=f\"[{self.options_scope}].config\",\n            discovery=cast(bool, self.options.config_discovery),\n            check_content=candidates,\n        )\n", "path": "src/python/pants/backend/python/lint/black/subsystem.py"}]}