Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow turning off export of Python tools like black (Cherry-pick of #15509) #15511

Merged
merged 1 commit into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/python/pants/backend/python/goals/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,13 @@ class ExportPythonToolSentinel:

@dataclass(frozen=True)
class ExportPythonTool(EngineAwareParameter):
"""How to export a particular Python tool.

If `pex_request=None`, the tool will be skipped.
"""

resolve_name: str
pex_request: PexRequest
pex_request: PexRequest | None

def debug_hint(self) -> str | None:
return self.resolve_name
Expand Down Expand Up @@ -146,6 +151,8 @@ async def export_virtualenv(

@rule
async def export_tool(request: ExportPythonTool, pex_pex: PexPEX) -> ExportResult:
assert request.pex_request is not None

# TODO: Unify export_virtualenv() and export_tool(), since their implementations mostly overlap.
dest = os.path.join("python", "virtualenvs", "tools")
pex = await Get(Pex, PexRequest, request.pex_request)
Expand Down Expand Up @@ -229,7 +236,9 @@ async def export_virtualenvs(
for tool_export_type in tool_export_types
)
all_tool_results = await MultiGet(
Get(ExportResult, ExportPythonTool, request) for request in all_export_tool_requests
Get(ExportResult, ExportPythonTool, request)
for request in all_export_tool_requests
if request.pex_request is not None
)

return ExportResults(venvs + all_tool_results)
Expand Down
5 changes: 4 additions & 1 deletion src/python/pants/backend/python/lint/autoflake/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pants.backend.python.goals import lockfile
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import ConsoleScript
from pants.core.goals.generate_lockfiles import GenerateToolLockfileSentinel
Expand Down Expand Up @@ -34,6 +34,7 @@ class Autoflake(PythonToolBase):

skip = SkipOption("fmt", "lint")
args = ArgsListOption(example="--target-version=py37 --quiet")
export = ExportToolOption()


class AutoflakeLockfileSentinel(GenerateToolLockfileSentinel):
Expand All @@ -55,6 +56,8 @@ class AutoflakeExportSentinel(ExportPythonToolSentinel):

@rule
def autoflake_export(_: AutoflakeExportSentinel, autoflake: Autoflake) -> ExportPythonTool:
if not autoflake.export:
return ExportPythonTool(resolve_name=autoflake.options_scope, pex_request=None)
return ExportPythonTool(
resolve_name=autoflake.options_scope, pex_request=autoflake.to_pex_request()
)
Expand Down
5 changes: 4 additions & 1 deletion src/python/pants/backend/python/lint/bandit/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.lint.bandit.skip_field import SkipBanditField
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import (
ConsoleScript,
Expand Down Expand Up @@ -64,6 +64,7 @@ class Bandit(PythonToolBase):

skip = SkipOption("lint")
args = ArgsListOption(example="--skip B101,B308 --confidence")
export = ExportToolOption()
config = FileOption(
"--config",
default=None,
Expand Down Expand Up @@ -138,6 +139,8 @@ class BanditExportSentinel(ExportPythonToolSentinel):
async def bandit_export(
_: BanditExportSentinel, bandit: Bandit, python_setup: PythonSetup
) -> ExportPythonTool:
if not bandit.export:
return ExportPythonTool(resolve_name=bandit.options_scope, pex_request=None)
constraints = await _bandit_interpreter_constraints(python_setup)
return ExportPythonTool(
resolve_name=bandit.options_scope,
Expand Down
7 changes: 5 additions & 2 deletions src/python/pants/backend/python/lint/black/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.lint.black.skip_field import SkipBlackField
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import ConsoleScript
from pants.backend.python.util_rules.interpreter_constraints import InterpreterConstraints
Expand Down Expand Up @@ -43,6 +43,7 @@ class Black(PythonToolBase):

skip = SkipOption("fmt", "lint")
args = ArgsListOption(example="--target-version=py37 --quiet")
export = ExportToolOption()
config = FileOption(
"--config",
default=None,
Expand Down Expand Up @@ -119,10 +120,12 @@ class BlackExportSentinel(ExportPythonToolSentinel):
pass


@rule(desc="Determine MyPy interpreter constraints (for `export` goal)", level=LogLevel.DEBUG)
@rule(desc="Determine Black interpreter constraints (for `export` goal)", level=LogLevel.DEBUG)
async def black_export(
_: BlackExportSentinel, black: Black, python_setup: PythonSetup
) -> ExportPythonTool:
if not black.export:
return ExportPythonTool(resolve_name=black.options_scope, pex_request=None)
constraints = await _black_interpreter_constraints(black, python_setup)
return ExportPythonTool(
resolve_name=black.options_scope,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pants.backend.python.goals import lockfile
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import ConsoleScript
from pants.core.goals.generate_lockfiles import GenerateToolLockfileSentinel
Expand Down Expand Up @@ -33,6 +33,7 @@ class Docformatter(PythonToolBase):

skip = SkipOption("fmt", "lint")
args = ArgsListOption(example="--wrap-summaries=100 --pre-summary-newline")
export = ExportToolOption()


class DocformatterLockfileSentinel(GenerateToolLockfileSentinel):
Expand All @@ -56,6 +57,8 @@ class DocformatterExportSentinel(ExportPythonToolSentinel):
def docformatter_export(
_: DocformatterExportSentinel, docformatter: Docformatter
) -> ExportPythonTool:
if not docformatter.export:
return ExportPythonTool(resolve_name=docformatter.options_scope, pex_request=None)
return ExportPythonTool(
resolve_name=docformatter.options_scope, pex_request=docformatter.to_pex_request()
)
Expand Down
5 changes: 4 additions & 1 deletion src/python/pants/backend/python/lint/flake8/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.lint.flake8.skip_field import SkipFlake8Field
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import (
ConsoleScript,
Expand Down Expand Up @@ -80,6 +80,7 @@ class Flake8(PythonToolBase):

skip = SkipOption("lint")
args = ArgsListOption(example="--ignore E123,W456 --enable-extensions H111")
export = ExportToolOption()
config = FileOption(
"--config",
default=None,
Expand Down Expand Up @@ -320,6 +321,8 @@ async def flake8_export(
first_party_plugins: Flake8FirstPartyPlugins,
python_setup: PythonSetup,
) -> ExportPythonTool:
if not flake8.export:
return ExportPythonTool(resolve_name=flake8.options_scope, pex_request=None)
constraints = await _flake8_interpreter_constraints(first_party_plugins, python_setup)
return ExportPythonTool(
resolve_name=flake8.options_scope,
Expand Down
5 changes: 4 additions & 1 deletion src/python/pants/backend/python/lint/isort/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pants.backend.python.goals import lockfile
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import ConsoleScript
from pants.core.goals.generate_lockfiles import GenerateToolLockfileSentinel
Expand Down Expand Up @@ -38,6 +38,7 @@ class Isort(PythonToolBase):

skip = SkipOption("fmt", "lint")
args = ArgsListOption(example="--case-sensitive --trailing-comma")
export = ExportToolOption()
config = FileListOption(
"--config",
# TODO: Figure out how to deprecate this being a list in favor of a single string.
Expand Down Expand Up @@ -112,6 +113,8 @@ class IsortExportSentinel(ExportPythonToolSentinel):

@rule
def isort_export(_: IsortExportSentinel, isort: Isort) -> ExportPythonTool:
if not isort.export:
return ExportPythonTool(resolve_name=isort.options_scope, pex_request=None)
return ExportPythonTool(resolve_name=isort.options_scope, pex_request=isort.to_pex_request())


Expand Down
5 changes: 4 additions & 1 deletion src/python/pants/backend/python/lint/pylint/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.lint.pylint.skip_field import SkipPylintField
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import (
ConsoleScript,
Expand Down Expand Up @@ -89,6 +89,7 @@ class Pylint(PythonToolBase):

skip = SkipOption("lint")
args = ArgsListOption(example="--ignore=foo.py,bar.py --disable=C0330,W0311")
export = ExportToolOption()
config = FileOption(
"--config",
default=None,
Expand Down Expand Up @@ -330,6 +331,8 @@ async def pylint_export(
first_party_plugins: PylintFirstPartyPlugins,
python_setup: PythonSetup,
) -> ExportPythonTool:
if not pylint.export:
return ExportPythonTool(resolve_name=pylint.options_scope, pex_request=None)
constraints = await _pylint_interpreter_constraints(first_party_plugins, python_setup)
return ExportPythonTool(
resolve_name=pylint.options_scope,
Expand Down
5 changes: 4 additions & 1 deletion src/python/pants/backend/python/lint/pyupgrade/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pants.backend.python.goals import lockfile
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import ConsoleScript
from pants.core.goals.generate_lockfiles import GenerateToolLockfileSentinel
Expand Down Expand Up @@ -36,6 +36,7 @@ class PyUpgrade(PythonToolBase):

skip = SkipOption("fmt", "lint")
args = ArgsListOption(example="--py39-plus --keep-runtime-typing")
export = ExportToolOption()


class PyUpgradeLockfileSentinel(GenerateToolLockfileSentinel):
Expand All @@ -57,6 +58,8 @@ class PyUpgradeExportSentinel(ExportPythonToolSentinel):

@rule
def pyupgrade_export(_: PyUpgradeExportSentinel, pyupgrade: PyUpgrade) -> ExportPythonTool:
if not pyupgrade.export:
return ExportPythonTool(resolve_name=pyupgrade.options_scope, pex_request=None)
return ExportPythonTool(
resolve_name=pyupgrade.options_scope, pex_request=pyupgrade.to_pex_request()
)
Expand Down
5 changes: 4 additions & 1 deletion src/python/pants/backend/python/lint/yapf/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pants.backend.python.goals import lockfile
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import ConsoleScript
from pants.core.goals.generate_lockfiles import GenerateToolLockfileSentinel
Expand Down Expand Up @@ -44,6 +44,7 @@ class Yapf(PythonToolBase):
"`--parallel`, will be ignored because Pants takes care of finding "
"all the relevant files and running the formatting in parallel.",
)
export = ExportToolOption()
config = FileOption(
"--config",
default=None,
Expand Down Expand Up @@ -107,6 +108,8 @@ class YapfExportSentinel(ExportPythonToolSentinel):

@rule
def yapf_export(_: YapfExportSentinel, yapf: Yapf) -> ExportPythonTool:
if not yapf.export:
return ExportPythonTool(resolve_name=yapf.options_scope, pex_request=None)
return ExportPythonTool(resolve_name=yapf.options_scope, pex_request=yapf.to_pex_request())


Expand Down
6 changes: 5 additions & 1 deletion src/python/pants/backend/python/subsystems/pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.pip_requirement import PipRequirement
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import (
ConsoleScript,
Expand Down Expand Up @@ -145,6 +145,8 @@ class PyTest(PythonToolBase):
),
)

export = ExportToolOption()

@property
def all_requirements(self) -> tuple[str, ...]:
return (self.version, *self.extra_requirements)
Expand Down Expand Up @@ -251,6 +253,8 @@ class PytestExportSentinel(ExportPythonToolSentinel):
async def pytest_export(
_: PytestExportSentinel, pytest: PyTest, python_setup: PythonSetup
) -> ExportPythonTool:
if not pytest.export:
return ExportPythonTool(resolve_name=pytest.options_scope, pex_request=None)
constraints = await _pytest_interpreter_constraints(python_setup)
return ExportPythonTool(
resolve_name=pytest.options_scope,
Expand Down
24 changes: 23 additions & 1 deletion src/python/pants/backend/python/subsystems/python_tool_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from pants.core.util_rules.lockfile_metadata import calculate_invalidation_digest
from pants.engine.fs import Digest, FileContent
from pants.option.errors import OptionsError
from pants.option.option_types import StrListOption, StrOption
from pants.option.option_types import BoolOption, StrListOption, StrOption
from pants.option.subsystem import Subsystem
from pants.util.docutil import bin_name, doc_url
from pants.util.strutil import softwrap
Expand Down Expand Up @@ -286,3 +286,25 @@ def to_pex_request(
main=main or self.main,
sources=sources,
)


class ExportToolOption(BoolOption):
"""An `--export` option to toggle whether the `export` goal should include the tool."""

def __new__(cls):
return super().__new__(
cls,
"--export",
default=True,
help=(
lambda subsystem_cls: softwrap(
f"""
If true, export a virtual environment with {subsystem_cls.name} when running
`{bin_name()} export`.

This can be useful, for example, with IDE integrations to point your editor to
the tool's binary.
"""
)
),
)
5 changes: 4 additions & 1 deletion src/python/pants/backend/python/typecheck/mypy/subsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from pants.backend.python.goals import lockfile
from pants.backend.python.goals.export import ExportPythonTool, ExportPythonToolSentinel
from pants.backend.python.goals.lockfile import GeneratePythonLockfile
from pants.backend.python.subsystems.python_tool_base import PythonToolBase
from pants.backend.python.subsystems.python_tool_base import ExportToolOption, PythonToolBase
from pants.backend.python.subsystems.setup import PythonSetup
from pants.backend.python.target_types import (
ConsoleScript,
Expand Down Expand Up @@ -93,6 +93,7 @@ class MyPy(PythonToolBase):

skip = SkipOption("check")
args = ArgsListOption(example="--python-version 3.7 --disallow-any-expr")
export = ExportToolOption()
config = FileOption(
"--config",
default=None,
Expand Down Expand Up @@ -355,6 +356,8 @@ async def mypy_export(
python_setup: PythonSetup,
first_party_plugins: MyPyFirstPartyPlugins,
) -> ExportPythonTool:
if not mypy.export:
return ExportPythonTool(resolve_name=mypy.options_scope, pex_request=None)
constraints = await _mypy_interpreter_constraints(mypy, python_setup)
return ExportPythonTool(
resolve_name=mypy.options_scope,
Expand Down