Skip to content

Commit

Permalink
Remove the concept of a scope category. (#10224)
Browse files Browse the repository at this point in the history
In v2 all optionables are subsystems, even global options.
There is no meaning to categories any more.

[ci skip-rust-tests]
  • Loading branch information
benjyw committed Jul 3, 2020
1 parent 4c391a5 commit 8500384
Show file tree
Hide file tree
Showing 19 changed files with 48 additions and 340 deletions.
21 changes: 2 additions & 19 deletions src/python/pants/engine/goal.py
Expand Up @@ -7,8 +7,6 @@
from typing import ClassVar, Tuple, Type

from pants.option.optionable import Optionable
from pants.option.options_bootstrapper import is_v2_exclusive
from pants.option.scope import ScopeInfo
from pants.subsystem.subsystem_client_mixin import SubsystemClientMixin
from pants.util.meta import classproperty

Expand All @@ -31,8 +29,6 @@ def list(console: Console, options: ListOptions) -> List:
```
"""

options_scope_category = ScopeInfo.GOAL

# If the goal requires downstream implementations to work properly, such as `test` and `run`,
# it should declare the union types that must have members.
required_union_implementations: Tuple[Type, ...] = ()
Expand All @@ -43,22 +39,9 @@ def name(cls):
"""The name used to select the corresponding Goal on the commandline and the options_scope
for its options."""

@classmethod
def conflict_free_name(cls):
# v2 goal names ending in '2' are assumed to be so-named to avoid conflict with a v1 goal.
# If we're in v2-exclusive mode, strip off the '2', so we can use the more natural name.
# Note that this implies a change of options scope when changing to v2-only mode: options
# on the foo2 scope will need to be moved to the foo scope. But we already expect options
# changes when switching to v2-exclusive mode (e.g., some v1 options aren't even registered
# in that mode), so this is in keeping with existing expectations. And this provides
# a much better experience to new users who never encountered v1 anyway.
if is_v2_exclusive and cls.name.endswith("2"):
return cls.name[:-1]
return cls.name

@classproperty
def options_scope(cls):
return cls.conflict_free_name()
return cls.name

def __init__(self, scope, scoped_options):
# NB: This constructor is shaped to meet the contract of `Optionable(Factory).signature`.
Expand Down Expand Up @@ -97,7 +80,7 @@ class List(Goal):

@classproperty
def name(cls):
return cls.subsystem_cls.conflict_free_name()
return cls.subsystem_cls.name


class Outputting:
Expand Down
38 changes: 8 additions & 30 deletions src/python/pants/help/help_printer.py
Expand Up @@ -11,9 +11,7 @@
from pants.base.build_environment import pants_release, pants_version
from pants.engine.goal import GoalSubsystem
from pants.engine.unions import UnionMembership
from pants.goal.goal import Goal
from pants.help.help_formatter import HelpFormatter
from pants.help.scope_info_iterator import ScopeInfoIterator
from pants.option.arg_splitter import (
GoalsHelp,
HelpRequest,
Expand Down Expand Up @@ -72,12 +70,7 @@ def _print_goals_help(self) -> None:
global_options = self._options.for_global_scope()
goal_descriptions: Dict[str, str] = {}
if global_options.v2:
goal_scope_infos = [
scope_info
for scope_info in self._options.known_scope_to_info.values()
if scope_info.category == ScopeInfo.GOAL
]
for scope_info in goal_scope_infos:
for scope_info in self._options.known_scope_to_info.values():
optionable_cls = scope_info.optionable_cls
if optionable_cls is None or not issubclass(optionable_cls, GoalSubsystem):
continue
Expand All @@ -88,31 +81,27 @@ def _print_goals_help(self) -> None:
continue
description = scope_info.description or "<no description>"
goal_descriptions[scope_info.scope] = description
if global_options.v1:
goal_descriptions.update(
{goal.name: goal.description_first_line for goal in Goal.all() if goal.description}
)

title_text = "Goals"
title = f"{title_text}\n{'-' * len(title_text)}"
if self._use_color:
title = green(title)

max_width = max(len(name) for name in goal_descriptions.keys())
max_width = max((len(name) for name in goal_descriptions.keys()), default=0)
chars_before_description = max_width + 2

def format_goal(name: str, description: str) -> str:
def format_goal(name: str, descr: str) -> str:
name = name.ljust(chars_before_description)
if self._use_color:
name = cyan(name)
description_lines = textwrap.wrap(description, 80 - chars_before_description)
description_lines = textwrap.wrap(descr, 80 - chars_before_description)
if len(description_lines) > 1:
description_lines = [
description_lines[0],
*(f"{' ' * chars_before_description}{line}" for line in description_lines[1:]),
]
description = "\n".join(description_lines)
return f"{name}{description}\n"
formatted_descr = "\n".join(description_lines)
return f"{name}{formatted_descr}\n"

lines = [
f"\n{title}\n",
Expand All @@ -134,23 +123,14 @@ def _print_options_help(self) -> None:
"""

help_request = cast(OptionsHelp, self._help_request)
global_options = self._options.for_global_scope()

if help_request.all_scopes:
help_scopes = set(self._options.known_scope_to_info.keys())
else:
# The scopes explicitly mentioned by the user on the cmd line.
help_scopes = set(self._options.scope_to_flags.keys()) - {GLOBAL_SCOPE}

# If --v1 is enabled at all, don't use v2_help, even if --v2 is also enabled.
v2_help = global_options.v2 and not global_options.v1

scope_info_iterator = ScopeInfoIterator(
scope_to_info=self._options.known_scope_to_info, v2_help=v2_help
)

scope_infos = list(scope_info_iterator.iterate(help_scopes))

scope_infos = list(self._options.known_scope_to_info[scope] for scope in help_scopes)
if scope_infos:
for scope_info in scope_infos:
help_str = self._format_help(scope_info, help_request.advanced)
Expand Down Expand Up @@ -188,9 +168,7 @@ def _print_options_help(self) -> None:
print(" dir:: to include all targets found recursively under the directory.")
print("\nFriendly docs:\n http://pantsbuild.org/")

print(
self._format_help(ScopeInfo(GLOBAL_SCOPE, ScopeInfo.GLOBAL), help_request.advanced)
)
print(self._format_help(ScopeInfo(GLOBAL_SCOPE), help_request.advanced))

def _format_help(self, scope_info: ScopeInfo, show_advanced_and_deprecated: bool) -> str:
"""Return a help message for the options registered on this object.
Expand Down
2 changes: 1 addition & 1 deletion src/python/pants/help/list_goals_integration_test.py
Expand Up @@ -20,7 +20,7 @@ def test_only_show_implemented_goals(self) -> None:
goals_that_need_implementation = ["binary", "fmt", "lint", "run", "test"]
command = ["--pants-config-files=[]", "goals"]

not_implemented_run = self.run_pants(command)
not_implemented_run = self.run_pants(["--backend-packages=[]", *command,])
self.assert_success(not_implemented_run)
for goal in goals_that_need_implementation:
assert goal not in not_implemented_run.stdout_data
Expand Down
93 changes: 0 additions & 93 deletions src/python/pants/help/scope_info_iterator.py

This file was deleted.

72 changes: 0 additions & 72 deletions src/python/pants/help/scope_info_iterator_test.py

This file was deleted.

2 changes: 1 addition & 1 deletion src/python/pants/option/arg_splitter.py
Expand Up @@ -270,7 +270,7 @@ def _descope_flag(self, flag: str, default_scope: str) -> Tuple[str, str]:
prefix = flag_prefix + scope_prefix
if flag.startswith(prefix):
scope = scope_info.scope
if scope_info.category == ScopeInfo.SUBSYSTEM and default_scope != GLOBAL_SCOPE:
if scope != GLOBAL_SCOPE and default_scope != GLOBAL_SCOPE:
# We allow goal.task --subsystem-foo to refer to the task-level subsystem instance,
# i.e., as if qualified by --subsystem-goal-task-foo.
# Note that this means that we can't set a task option on the cmd-line if its
Expand Down
28 changes: 8 additions & 20 deletions src/python/pants/option/arg_splitter_test.py
Expand Up @@ -18,28 +18,16 @@
from pants.util.contextutil import pushd, temporary_dir


def task(scope: str) -> ScopeInfo:
return ScopeInfo(scope, ScopeInfo.TASK)


def intermediate(scope: str) -> ScopeInfo:
return ScopeInfo(scope, ScopeInfo.INTERMEDIATE)


def subsys(scope: str) -> ScopeInfo:
return ScopeInfo(scope, ScopeInfo.SUBSYSTEM)


class ArgSplitterTest(unittest.TestCase):
_known_scope_infos = [
intermediate("compile"),
task("compile.java"),
task("compile.scala"),
subsys("jvm"),
subsys("jvm.test.junit"),
subsys("reporting"),
intermediate("test"),
task("test.junit"),
ScopeInfo("compile"),
ScopeInfo("compile.java"),
ScopeInfo("compile.scala"),
ScopeInfo("jvm"),
ScopeInfo("jvm.test.junit"),
ScopeInfo("reporting"),
ScopeInfo("test"),
ScopeInfo("test.junit"),
]

def assert_valid_split(
Expand Down
3 changes: 1 addition & 2 deletions src/python/pants/option/global_options.py
Expand Up @@ -18,7 +18,7 @@
)
from pants.option.custom_types import dir_option
from pants.option.errors import OptionsError
from pants.option.scope import GLOBAL_SCOPE, ScopeInfo
from pants.option.scope import GLOBAL_SCOPE
from pants.subsystem.subsystem import Subsystem
from pants.util.logging import LogLevel

Expand Down Expand Up @@ -146,7 +146,6 @@ def from_bootstrap_options(cls, bootstrap_options):

class GlobalOptions(Subsystem):
options_scope = GLOBAL_SCOPE
options_scope_category = ScopeInfo.GLOBAL

@classmethod
def register_bootstrap_options(cls, register):
Expand Down

0 comments on commit 8500384

Please sign in to comment.