diff --git a/pants-plugins/src/python/internal_backend/rules_for_testing/register.py b/pants-plugins/src/python/internal_backend/rules_for_testing/register.py index 08c5ece908a..c25eb3150eb 100644 --- a/pants-plugins/src/python/internal_backend/rules_for_testing/register.py +++ b/pants-plugins/src/python/internal_backend/rules_for_testing/register.py @@ -9,12 +9,12 @@ from pants.engine.addressable import BuildFileAddresses from pants.engine.console import Console from pants.engine.rules import console_rule -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.option.scope import Scope, ScopedOptions from pants.rules.core.exceptions import GracefulTerminationException -@console_rule('list-and-die-for-testing', [Select(Console), Select(BuildFileAddresses)]) +@console_rule('list-and-die-for-testing', [Console, BuildFileAddresses]) def fast_list_and_die_for_testing(console, addresses): """A fast and deadly variant of `./pants list`.""" options = yield Get(ScopedOptions, Scope(str('list'))) diff --git a/src/python/pants/backend/native/subsystems/binaries/binutils.py b/src/python/pants/backend/native/subsystems/binaries/binutils.py index d8b3375b0c4..1d5abcb0528 100644 --- a/src/python/pants/backend/native/subsystems/binaries/binutils.py +++ b/src/python/pants/backend/native/subsystems/binaries/binutils.py @@ -9,7 +9,6 @@ from pants.backend.native.config.environment import Assembler, Linker from pants.binaries.binary_tool import NativeTool from pants.engine.rules import rule -from pants.engine.selectors import Select class Binutils(NativeTool): @@ -38,12 +37,12 @@ def linker(self): ) -@rule(Assembler, [Select(Binutils)]) +@rule(Assembler, [Binutils]) def get_as(binutils): return binutils.assembler() -@rule(Linker, [Select(Binutils)]) +@rule(Linker, [Binutils]) def get_ld(binutils): return binutils.linker() diff --git a/src/python/pants/backend/native/subsystems/binaries/gcc.py b/src/python/pants/backend/native/subsystems/binaries/gcc.py index b0696375d79..3535ef1a59a 100644 --- a/src/python/pants/backend/native/subsystems/binaries/gcc.py +++ b/src/python/pants/backend/native/subsystems/binaries/gcc.py @@ -10,7 +10,6 @@ from pants.backend.native.subsystems.utils.archive_file_mapper import ArchiveFileMapper from pants.binaries.binary_tool import NativeTool from pants.engine.rules import rule -from pants.engine.selectors import Select from pants.util.memo import memoized_method, memoized_property @@ -96,12 +95,12 @@ def cpp_compiler(self, platform): extra_args=[]) -@rule(CCompiler, [Select(GCC), Select(Platform)]) +@rule(CCompiler, [GCC, Platform]) def get_gcc(gcc, platform): return gcc.c_compiler(platform) -@rule(CppCompiler, [Select(GCC), Select(Platform)]) +@rule(CppCompiler, [GCC, Platform]) def get_gplusplus(gcc, platform): return gcc.cpp_compiler(platform) diff --git a/src/python/pants/backend/native/subsystems/binaries/llvm.py b/src/python/pants/backend/native/subsystems/binaries/llvm.py index 9786e5c3990..dfd816b7151 100644 --- a/src/python/pants/backend/native/subsystems/binaries/llvm.py +++ b/src/python/pants/backend/native/subsystems/binaries/llvm.py @@ -11,7 +11,6 @@ from pants.binaries.binary_tool import NativeTool from pants.binaries.binary_util import BinaryToolUrlGenerator from pants.engine.rules import RootRule, rule -from pants.engine.selectors import Select from pants.util.dirutil import is_readable_dir from pants.util.memo import memoized_method, memoized_property @@ -123,17 +122,17 @@ def cpp_compiler(self): # TODO(#5663): use this over the XCode linker! -@rule(Linker, [Select(Platform), Select(LLVM)]) +@rule(Linker, [Platform, LLVM]) def get_lld(platform, llvm): return llvm.linker(platform) -@rule(CCompiler, [Select(LLVM)]) +@rule(CCompiler, [LLVM]) def get_clang(llvm): return llvm.c_compiler() -@rule(CppCompiler, [Select(LLVM)]) +@rule(CppCompiler, [LLVM]) def get_clang_plusplus(llvm): return llvm.cpp_compiler() diff --git a/src/python/pants/backend/native/subsystems/native_toolchain.py b/src/python/pants/backend/native/subsystems/native_toolchain.py index aa0248adc34..ff749d35051 100644 --- a/src/python/pants/backend/native/subsystems/native_toolchain.py +++ b/src/python/pants/backend/native/subsystems/native_toolchain.py @@ -15,7 +15,7 @@ from pants.backend.native.subsystems.native_build_step import ToolchainVariant from pants.backend.native.subsystems.xcode_cli_tools import XCodeCLITools from pants.engine.rules import RootRule, rule -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.subsystem.subsystem import Subsystem from pants.util.memo import memoized_property from pants.util.objects import datatype @@ -98,7 +98,7 @@ class LLVMCToolchain(datatype([('c_toolchain', CToolchain)])): pass class LLVMCppToolchain(datatype([('cpp_toolchain', CppToolchain)])): pass -@rule(LibcObjects, [Select(Platform), Select(NativeToolchain)]) +@rule(LibcObjects, [Platform, NativeToolchain]) def select_libc_objects(platform, native_toolchain): # We use lambdas here to avoid searching for libc on osx, where it will fail. paths = platform.resolve_for_enum_variant({ @@ -108,7 +108,7 @@ def select_libc_objects(platform, native_toolchain): yield LibcObjects(paths) -@rule(Assembler, [Select(Platform), Select(NativeToolchain)]) +@rule(Assembler, [Platform, NativeToolchain]) def select_assembler(platform, native_toolchain): if platform == Platform.darwin: assembler = yield Get(Assembler, XCodeCLITools, native_toolchain._xcode_cli_tools) @@ -125,7 +125,7 @@ class BaseLinker(datatype([('linker', Linker)])): # TODO: select the appropriate `Platform` in the `@rule` decl using variants! -@rule(BaseLinker, [Select(Platform), Select(NativeToolchain)]) +@rule(BaseLinker, [Platform, NativeToolchain]) def select_base_linker(platform, native_toolchain): if platform == Platform.darwin: # TODO(#5663): turn this into LLVM when lld works. @@ -136,7 +136,7 @@ def select_base_linker(platform, native_toolchain): yield base_linker -@rule(GCCLinker, [Select(NativeToolchain)]) +@rule(GCCLinker, [NativeToolchain]) def select_gcc_linker(native_toolchain): base_linker = yield Get(BaseLinker, NativeToolchain, native_toolchain) linker = base_linker.linker @@ -145,7 +145,7 @@ def select_gcc_linker(native_toolchain): yield GCCLinker(linker_with_libc) -@rule(LLVMLinker, [Select(BaseLinker)]) +@rule(LLVMLinker, [BaseLinker]) def select_llvm_linker(base_linker): return LLVMLinker(base_linker.linker) @@ -163,12 +163,12 @@ def as_clang_argv(self): return ['--gcc-toolchain={}'.format(self.toolchain_dir)] -@rule(GCCInstallLocationForLLVM, [Select(GCC)]) +@rule(GCCInstallLocationForLLVM, [GCC]) def select_gcc_install_location(gcc): return GCCInstallLocationForLLVM(gcc.select()) -@rule(LLVMCToolchain, [Select(Platform), Select(NativeToolchain)]) +@rule(LLVMCToolchain, [Platform, NativeToolchain]) def select_llvm_c_toolchain(platform, native_toolchain): provided_clang = yield Get(CCompiler, LLVM, native_toolchain._llvm) @@ -194,7 +194,7 @@ def select_llvm_c_toolchain(platform, native_toolchain): yield LLVMCToolchain(CToolchain(working_c_compiler, working_linker)) -@rule(LLVMCppToolchain, [Select(Platform), Select(NativeToolchain)]) +@rule(LLVMCppToolchain, [Platform, NativeToolchain]) def select_llvm_cpp_toolchain(platform, native_toolchain): provided_clangpp = yield Get(CppCompiler, LLVM, native_toolchain._llvm) @@ -238,7 +238,7 @@ def select_llvm_cpp_toolchain(platform, native_toolchain): yield LLVMCppToolchain(CppToolchain(working_cpp_compiler, working_linker)) -@rule(GCCCToolchain, [Select(Platform), Select(NativeToolchain)]) +@rule(GCCCToolchain, [Platform, NativeToolchain]) def select_gcc_c_toolchain(platform, native_toolchain): provided_gcc = yield Get(CCompiler, GCC, native_toolchain._gcc) @@ -263,7 +263,7 @@ def select_gcc_c_toolchain(platform, native_toolchain): yield GCCCToolchain(CToolchain(working_c_compiler, working_linker)) -@rule(GCCCppToolchain, [Select(Platform), Select(NativeToolchain)]) +@rule(GCCCppToolchain, [Platform, NativeToolchain]) def select_gcc_cpp_toolchain(platform, native_toolchain): provided_gpp = yield Get(CppCompiler, GCC, native_toolchain._gcc) @@ -301,7 +301,7 @@ class ToolchainVariantRequest(datatype([ ])): pass -@rule(CToolchain, [Select(ToolchainVariantRequest)]) +@rule(CToolchain, [ToolchainVariantRequest]) def select_c_toolchain(toolchain_variant_request): native_toolchain = toolchain_variant_request.toolchain # TODO(#5933): make an enum exhaustiveness checking method that works with `yield Get(...)`! @@ -316,7 +316,7 @@ def select_c_toolchain(toolchain_variant_request): yield toolchain_resolved.c_toolchain -@rule(CppToolchain, [Select(ToolchainVariantRequest)]) +@rule(CppToolchain, [ToolchainVariantRequest]) def select_cpp_toolchain(toolchain_variant_request): native_toolchain = toolchain_variant_request.toolchain # TODO(#5933): make an enum exhaustiveness checking method that works with `yield Get(...)`! diff --git a/src/python/pants/backend/native/subsystems/xcode_cli_tools.py b/src/python/pants/backend/native/subsystems/xcode_cli_tools.py index 3c2e472785c..ffde1b52fe1 100644 --- a/src/python/pants/backend/native/subsystems/xcode_cli_tools.py +++ b/src/python/pants/backend/native/subsystems/xcode_cli_tools.py @@ -8,7 +8,6 @@ from pants.backend.native.config.environment import Assembler, CCompiler, CppCompiler, Linker from pants.engine.rules import rule -from pants.engine.selectors import Select from pants.subsystem.subsystem import Subsystem from pants.util.dirutil import is_readable_dir from pants.util.memo import memoized_method, memoized_property @@ -167,22 +166,22 @@ def cpp_compiler(self): extra_args=[MIN_OSX_VERSION_ARG]) -@rule(Assembler, [Select(XCodeCLITools)]) +@rule(Assembler, [XCodeCLITools]) def get_assembler(xcode_cli_tools): return xcode_cli_tools.assembler() -@rule(Linker, [Select(XCodeCLITools)]) +@rule(Linker, [XCodeCLITools]) def get_ld(xcode_cli_tools): return xcode_cli_tools.linker() -@rule(CCompiler, [Select(XCodeCLITools)]) +@rule(CCompiler, [XCodeCLITools]) def get_clang(xcode_cli_tools): return xcode_cli_tools.c_compiler() -@rule(CppCompiler, [Select(XCodeCLITools)]) +@rule(CppCompiler, [XCodeCLITools]) def get_clang_plusplus(xcode_cli_tools): return xcode_cli_tools.cpp_compiler() diff --git a/src/python/pants/backend/python/rules/python_test_runner.py b/src/python/pants/backend/python/rules/python_test_runner.py index 26ac23c39e5..6a92e7e56a3 100644 --- a/src/python/pants/backend/python/rules/python_test_runner.py +++ b/src/python/pants/backend/python/rules/python_test_runner.py @@ -14,7 +14,7 @@ FallibleExecuteProcessResult) from pants.engine.legacy.graph import TransitiveHydratedTarget from pants.engine.rules import optionable_rule, rule -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.rules.core.core_test_model import Status, TestResult @@ -27,7 +27,7 @@ class PyTestResult(TestResult): # TODO: Support deps # TODO: Support resources -@rule(PyTestResult, [Select(TransitiveHydratedTarget), Select(PyTest)]) +@rule(PyTestResult, [TransitiveHydratedTarget, PyTest]) def run_python_test(transitive_hydrated_target, pytest): target_root = transitive_hydrated_target.root diff --git a/src/python/pants/engine/README.md b/src/python/pants/engine/README.md index bc8c40bcf5f..99b8dc9282f 100644 --- a/src/python/pants/engine/README.md +++ b/src/python/pants/engine/README.md @@ -46,15 +46,15 @@ As a very simple example, you might register the following `@rule` that can comp Product given a single `Int` input. ```python -@rule(StringType, [Select(IntType)]) +@rule(StringType, [IntType]) def int_to_str(an_int): return '{}'.format(an_int) ``` The first argument to the `@rule` decorator is the Product (ie, return) type for the `@rule`. The -second argument is a list of `Selector`s that declare the types of the input arguments to the -`@rule`. In this case, because the Product type is `StringType` and there is one `Selector` -(`Select(IntType)`), this `@rule` represents a conversion from `IntType` to `StrType`, with no +second argument is a list of parameter selectors that declare the types of the input parameters for +the `@rule`. In this case, because the Product type is `StringType` and there is one parameter +selector (for `IntType`), this `@rule` represents a conversion from `IntType` to `StrType`, with no other inputs. When the engine statically checks whether it can use this `@rule` to create a string for a @@ -73,7 +73,7 @@ definitions to provide a unique and descriptive type is strongly recommended: ```python class FormattedInt(datatype(['content'])): pass -@rule(FormattedInt, [Select(IntType)]) +@rule(FormattedInt, [IntType]) def int_to_str(an_int): return FormattedInt('{}'.format(an_int)) @@ -113,15 +113,15 @@ formalize the assumptions made about the value of an object into a specific type just wraps a single field. The `datatype()` function makes it simple and efficient to apply that strategy. -### Selectors and Gets +### Parameter selectors and Gets -As demonstrated above, the `Selector` classes select `@rule` inputs in the context of a particular +As demonstrated above, parameter selectors select `@rule` inputs in the context of a particular `Subject` (and its `Variants`: discussed below). But it is frequently necessary to "change" the subject and request products for subjects other than the one that the `@rule` is running for. In cases where this is necessary, `@rule`s may be written as coroutines (ie, using the python `yield` statement) that yield "`Get` requests" that request products for other subjects. Just like -`@rule` parameter Selectors, `Get` requests instantiated in the body of an `@rule` are statically +`@rule` parameter selectors, `Get` requests instantiated in the body of an `@rule` are statically checked to be satisfiable in the set of installed `@rule`s. #### Example @@ -130,7 +130,7 @@ For example, you could declare an `@rule` that requests FileContent for each ent and then concatentates that content into a (typed) string: ```python -@rule(ConcattedFiles, [Select(Files)]) +@rule(ConcattedFiles, [Files]) def concat(files): file_content_list = yield [Get(FileContent, File(f)) for f in files] yield ConcattedFiles(''.join(fc.content for fc in file_content_list)) @@ -184,8 +184,8 @@ given set of rules. In general, there are three types of rules you can define: 1. an `@rule`, which has a single product type and selects its inputs as described above. -2. a `SingletonRule`, which matches a product type with a value so the type can then be `Select`ed - in an `@rule`. +2. a `SingletonRule`, which matches a product type with a value so the type can then be selected + as a parameter to an `@rule`. 3. a `RootRule`, which declares a type that can be used as a *subject*, which means it can be provided as an input to a `product_request()`. diff --git a/src/python/pants/engine/build_files.py b/src/python/pants/engine/build_files.py index 84430073f35..474c465d084 100644 --- a/src/python/pants/engine/build_files.py +++ b/src/python/pants/engine/build_files.py @@ -22,7 +22,7 @@ from pants.engine.objects import Locatable, SerializableFactory, Validatable from pants.engine.parser import TargetAdaptorContainer from pants.engine.rules import RootRule, SingletonRule, rule -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.engine.struct import Struct from pants.util.collections_abc_backport import MutableMapping, MutableSequence from pants.util.objects import TypeConstraintError, datatype @@ -40,7 +40,7 @@ def _key_func(entry): return key -@rule(AddressFamily, [Select(AddressMapper), Select(Dir)]) +@rule(AddressFamily, [AddressMapper, Dir]) def parse_address_family(address_mapper, directory): """Given an AddressMapper and a directory, return an AddressFamily. @@ -89,7 +89,7 @@ def _raise_did_you_mean(address_family, name, source=None): raise resolve_error -@rule(UnhydratedStruct, [Select(AddressMapper), Select(Address)]) +@rule(UnhydratedStruct, [AddressMapper, Address]) def resolve_unhydrated_struct(address_mapper, address): """Given an AddressMapper and an Address, resolve an UnhydratedStruct. @@ -135,7 +135,7 @@ def collect_dependencies(item): dependencies) -@rule(TargetAdaptorContainer, [Select(AddressMapper), Select(UnhydratedStruct)]) +@rule(TargetAdaptorContainer, [AddressMapper, UnhydratedStruct]) def hydrate_struct(address_mapper, unhydrated_struct): """Hydrates a Struct from an UnhydratedStruct and its satisfied embedded addressable deps. @@ -208,7 +208,7 @@ def _hydrate(item_type, spec_path, **kwargs): return item -@rule(BuildFileAddresses, [Select(AddressMapper), Select(Specs)]) +@rule(BuildFileAddresses, [AddressMapper, Specs]) def addresses_from_address_families(address_mapper, specs): """Given an AddressMapper and list of Specs, return matching BuildFileAddresses. diff --git a/src/python/pants/engine/isolated_process.py b/src/python/pants/engine/isolated_process.py index 96a42adc289..eac109f923b 100644 --- a/src/python/pants/engine/isolated_process.py +++ b/src/python/pants/engine/isolated_process.py @@ -10,7 +10,6 @@ from pants.engine.fs import Digest from pants.engine.rules import RootRule, rule -from pants.engine.selectors import Select from pants.util.objects import Exactly, TypeCheckError, datatype @@ -113,7 +112,7 @@ def __init__(self, exit_code, stdout, stderr, process_description): super(ProcessExecutionFailure, self).__init__(msg) -@rule(ExecuteProcessResult, [Select(FallibleExecuteProcessResult), Select(ExecuteProcessRequest)]) +@rule(ExecuteProcessResult, [FallibleExecuteProcessResult, ExecuteProcessRequest]) def fallible_to_exec_result_or_raise(fallible_result, request): """Converts a FallibleExecuteProcessResult to a ExecuteProcessResult or raises an error.""" diff --git a/src/python/pants/engine/legacy/graph.py b/src/python/pants/engine/legacy/graph.py index ab8420713ad..e3cb16a4b8f 100644 --- a/src/python/pants/engine/legacy/graph.py +++ b/src/python/pants/engine/legacy/graph.py @@ -30,7 +30,7 @@ from pants.engine.objects import Collection from pants.engine.parser import SymbolTable, TargetAdaptorContainer from pants.engine.rules import RootRule, rule -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.option.global_options import GlobMatchErrorBehavior from pants.source.filespec import any_matches_filespec from pants.source.wrapped_globs import EagerFilesetWithSpec, FilesetRelPathWrapper @@ -409,7 +409,7 @@ class OwnersRequest(datatype([ """ -@rule(BuildFileAddresses, [Select(SymbolTable), Select(AddressMapper), Select(OwnersRequest)]) +@rule(BuildFileAddresses, [SymbolTable, AddressMapper, OwnersRequest]) def find_owners(symbol_table, address_mapper, owners_request): sources_set = OrderedSet(owners_request.sources) dirs_set = OrderedSet(dirname(source) for source in sources_set) @@ -459,7 +459,7 @@ def owns_any_source(legacy_target): yield BuildFileAddresses(tuple(graph.transitive_dependents_of_addresses(direct_owners))) -@rule(TransitiveHydratedTargets, [Select(BuildFileAddresses)]) +@rule(TransitiveHydratedTargets, [BuildFileAddresses]) def transitive_hydrated_targets(build_file_addresses): """Given BuildFileAddresses, kicks off recursion on expansion of TransitiveHydratedTargets. @@ -485,13 +485,13 @@ def transitive_hydrated_targets(build_file_addresses): yield TransitiveHydratedTargets(tuple(tht.root for tht in transitive_hydrated_targets), closure) -@rule(TransitiveHydratedTarget, [Select(HydratedTarget)]) +@rule(TransitiveHydratedTarget, [HydratedTarget]) def transitive_hydrated_target(root): dependencies = yield [Get(TransitiveHydratedTarget, Address, d) for d in root.dependencies] yield TransitiveHydratedTarget(root, dependencies) -@rule(HydratedTargets, [Select(BuildFileAddresses)]) +@rule(HydratedTargets, [BuildFileAddresses]) def hydrated_targets(build_file_addresses): """Requests HydratedTarget instances for BuildFileAddresses.""" targets = yield [Get(HydratedTarget, Address, a) for a in build_file_addresses.addresses] @@ -502,7 +502,7 @@ class HydratedField(datatype(['name', 'value'])): """A wrapper for a fully constructed replacement kwarg for a HydratedTarget.""" -@rule(HydratedTarget, [Select(TargetAdaptorContainer)]) +@rule(HydratedTarget, [TargetAdaptorContainer]) def hydrate_target(target_adaptor_container): target_adaptor = target_adaptor_container.value """Construct a HydratedTarget from a TargetAdaptor and hydrated versions of its adapted fields.""" @@ -531,7 +531,7 @@ def _eager_fileset_with_spec(spec_path, filespec, snapshot, include_dirs=False): include_dirs=include_dirs) -@rule(HydratedField, [Select(SourcesField), Select(GlobMatchErrorBehavior)]) +@rule(HydratedField, [SourcesField, GlobMatchErrorBehavior]) def hydrate_sources(sources_field, glob_match_error_behavior): """Given a SourcesField, request a Snapshot for its path_globs and create an EagerFilesetWithSpec. """ @@ -547,7 +547,7 @@ def hydrate_sources(sources_field, glob_match_error_behavior): yield HydratedField(sources_field.arg, fileset_with_spec) -@rule(HydratedField, [Select(BundlesField), Select(GlobMatchErrorBehavior)]) +@rule(HydratedField, [BundlesField, GlobMatchErrorBehavior]) def hydrate_bundles(bundles_field, glob_match_error_behavior): """Given a BundlesField, request Snapshots for each of its filesets and create BundleAdaptors.""" path_globs_with_match_errors = [ diff --git a/src/python/pants/engine/legacy/options_parsing.py b/src/python/pants/engine/legacy/options_parsing.py index 3d611fb433f..c70d62e7f17 100644 --- a/src/python/pants/engine/legacy/options_parsing.py +++ b/src/python/pants/engine/legacy/options_parsing.py @@ -5,7 +5,6 @@ from __future__ import absolute_import, division, print_function, unicode_literals from pants.engine.rules import RootRule, rule -from pants.engine.selectors import Select from pants.init.options_initializer import BuildConfigInitializer, OptionsInitializer from pants.option.options import Options from pants.option.options_bootstrapper import OptionsBootstrapper @@ -17,7 +16,7 @@ class _Options(datatype([('options', Options)])): """A wrapper around bootstrapped options values: not for direct consumption.""" -@rule(_Options, [Select(OptionsBootstrapper)]) +@rule(_Options, [OptionsBootstrapper]) def parse_options(options_bootstrapper): # TODO: Because _OptionsBootstapper is currently provided as a Param, this @rule relies on options # remaining relatively stable in order to be efficient. See #6845 for a discussion of how to make @@ -26,7 +25,7 @@ def parse_options(options_bootstrapper): return _Options(OptionsInitializer.create(options_bootstrapper, build_config, init_subsystems=False)) -@rule(ScopedOptions, [Select(Scope), Select(_Options)]) +@rule(ScopedOptions, [Scope, _Options]) def scope_options(scope, options): return ScopedOptions(scope, options.options.for_scope(scope.scope)) diff --git a/src/python/pants/engine/rules.py b/src/python/pants/engine/rules.py index 30172489a88..9f0d65e01f2 100644 --- a/src/python/pants/engine/rules.py +++ b/src/python/pants/engine/rules.py @@ -23,7 +23,7 @@ from pants.util.collections_abc_backport import Iterable, OrderedDict from pants.util.memo import memoized from pants.util.meta import AbstractClass -from pants.util.objects import SubclassesOf, datatype +from pants.util.objects import SubclassesOf, TypedCollection, datatype logger = logging.getLogger(__name__) @@ -330,7 +330,7 @@ def union(cls): @union class UnionBase(object): pass - @rule(B, [Select(X)]) + @rule(B, [X]) def get_some_union_type(x): result = yield Get(ResultType, UnionBase, x.f()) # ... @@ -382,7 +382,7 @@ def dependency_optionables(self): class TaskRule(datatype([ ('output_type', _type_field), - ('input_selectors', tuple), + ('input_selectors', TypedCollection(SubclassesOf(type))), ('input_gets', tuple), 'func', 'goal', diff --git a/src/python/pants/engine/scheduler.py b/src/python/pants/engine/scheduler.py index 1fbaf40fc3c..9e9b1e35ea4 100644 --- a/src/python/pants/engine/scheduler.py +++ b/src/python/pants/engine/scheduler.py @@ -20,7 +20,7 @@ from pants.engine.nodes import Return, Throw from pants.engine.objects import Collection from pants.engine.rules import RuleIndex, SingletonRule, TaskRule -from pants.engine.selectors import Params, Select +from pants.engine.selectors import Params from pants.rules.core.exceptions import GracefulTerminationException from pants.util.contextutil import temporary_file_path from pants.util.dirutil import check_no_overlapping_paths @@ -202,11 +202,7 @@ def _register_task(self, output_type, rule, union_rules): func = Function(self._to_key(rule.func)) self._native.lib.tasks_task_begin(self._tasks, func, self._to_type(output_type), rule.cacheable) for selector in rule.input_selectors: - selector_type = type(selector) - if selector_type is Select: - self._native.lib.tasks_add_select(self._tasks, self._to_type(selector.product)) - else: - raise ValueError('Unrecognized Selector type: {}'.format(selector)) + self._native.lib.tasks_add_select(self._tasks, self._to_type(selector)) def add_get_edge(product, subject): self._native.lib.tasks_add_get(self._tasks, self._to_type(product), self._to_type(subject)) diff --git a/src/python/pants/engine/selectors.py b/src/python/pants/engine/selectors.py index 99b450c840a..9d7462b1e10 100644 --- a/src/python/pants/engine/selectors.py +++ b/src/python/pants/engine/selectors.py @@ -102,18 +102,3 @@ class Params(datatype([('params', tuple)])): def __new__(cls, *args): return super(Params, cls).__new__(cls, tuple(args)) - - -class Select(datatype([('product', _type_field), ('optional', bool)])): - """Selects the given Product for the Subject provided to the constructor. - - If optional=True and no matching product can be produced, will return None. - """ - - def __new__(cls, product, optional=False): - return super(Select, cls).__new__(cls, product, optional) - - def __repr__(self): - return '{}({}{})'.format(type(self).__name__, - self.product.__name__, - ', optional=True' if self.optional else '') diff --git a/src/python/pants/rules/core/fastlist.py b/src/python/pants/rules/core/fastlist.py index 192565917e2..b5129db2761 100644 --- a/src/python/pants/rules/core/fastlist.py +++ b/src/python/pants/rules/core/fastlist.py @@ -9,7 +9,7 @@ from pants.engine.console import Console from pants.engine.legacy.graph import HydratedTargets from pants.engine.rules import console_rule, optionable_rule -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.subsystem.subsystem import Subsystem @@ -36,7 +36,7 @@ def register_options(cls, register): help='Print only targets that are documented with a description.') -@console_rule('list', [Select(Console), Select(ListOptions), Select(Specs)]) +@console_rule('list', [Console, ListOptions, Specs]) def fast_list(console, options, specs): """A fast variant of `./pants list` with a reduced feature set.""" diff --git a/src/python/pants/rules/core/filedeps.py b/src/python/pants/rules/core/filedeps.py index ea1fc8cd03e..4452a2cd9fc 100644 --- a/src/python/pants/rules/core/filedeps.py +++ b/src/python/pants/rules/core/filedeps.py @@ -9,10 +9,9 @@ from pants.engine.console import Console from pants.engine.legacy.graph import TransitiveHydratedTargets from pants.engine.rules import console_rule -from pants.engine.selectors import Select -@console_rule('filedeps', [Select(Console), Select(TransitiveHydratedTargets)]) +@console_rule('filedeps', [Console, TransitiveHydratedTargets]) def file_deps(console, transitive_hydrated_targets): """List all source and BUILD files a target transitively depends on. diff --git a/src/python/pants/rules/core/test.py b/src/python/pants/rules/core/test.py index a8604abed7e..b25d1f34eb4 100644 --- a/src/python/pants/rules/core/test.py +++ b/src/python/pants/rules/core/test.py @@ -11,12 +11,12 @@ from pants.engine.console import Console from pants.engine.legacy.graph import HydratedTarget from pants.engine.rules import console_rule, rule -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.rules.core.core_test_model import Status, TestResult from pants.rules.core.exceptions import GracefulTerminationException -@console_rule('test', [Select(Console), Select(BuildFileAddresses)]) +@console_rule('test', [Console, BuildFileAddresses]) def fast_test(console, addresses): test_results = yield [Get(TestResult, Address, address.to_address()) for address in addresses] wrote_any_stdout = False @@ -40,7 +40,7 @@ def fast_test(console, addresses): raise GracefulTerminationException("Tests failed", exit_code=PANTS_FAILED_EXIT_CODE) -@rule(TestResult, [Select(HydratedTarget)]) +@rule(TestResult, [HydratedTarget]) def coordinator_of_tests(target): # This should do an instance match, or canonicalise the adaptor type, or something #if isinstance(target.adaptor, PythonTestsAdaptor): diff --git a/src/rust/engine/src/rule_graph.rs b/src/rust/engine/src/rule_graph.rs index c724e4f45c9..6c59a20e4b8 100644 --- a/src/rust/engine/src/rule_graph.rs +++ b/src/rust/engine/src/rule_graph.rs @@ -192,7 +192,7 @@ impl Diagnostic { Diagnostic { params: available_params.clone(), reason: format!( - "ambiguous rules for {}{}{}", + "Ambiguous rules to compute {}{}{}", select_key_str(&key), params_clause, params_str(&available_params), @@ -792,13 +792,13 @@ pub fn params_str(params: &ParamTypes) -> String { pub fn select_key_str(select_key: &SelectKey) -> String { match select_key { - &SelectKey::JustSelect(ref s) => select_str(s), + &SelectKey::JustSelect(ref s) => s.product.to_string(), &SelectKey::JustGet(ref g) => get_str(g), } } -pub fn select_str(select: &Select) -> String { - format!("Select({})", select.product).to_string() // TODO variant key +pub fn select_root_str(select: &Select) -> String { + format!("Select({})", select.product) } fn get_str(get: &Get) -> String { @@ -828,7 +828,7 @@ fn entry_with_deps_str(entry: &EntryWithDeps) -> String { rule: Rule::Intrinsic(ref intrinsic), ref params, }) => format!( - "({}, ({},) for {}", + "({}, [{}], ) for {}", intrinsic.product, intrinsic.input, params_str(params) @@ -838,7 +838,7 @@ fn entry_with_deps_str(entry: &EntryWithDeps) -> String { root .clause .iter() - .map(|s| select_str(s)) + .map(|s| select_root_str(s)) .collect::>() .join(", "), params_str(&root.params) @@ -851,7 +851,7 @@ fn task_display(task: &Task) -> String { let mut clause_portion = task .clause .iter() - .map(|c| select_str(c)) + .map(|c| c.product.to_string()) .collect::>() .join(", "); clause_portion = format!("[{}]", clause_portion); @@ -915,7 +915,7 @@ impl RuleGraph { 1 => Ok(subset_matches[0].1.clone()), 0 => Err(format!( "No installed @rules can satisfy {} for input Params({}).", - select_str(&select), + select_root_str(&select), params_str(¶ms), )), _ => { @@ -925,7 +925,7 @@ impl RuleGraph { .collect::>(); Err(format!( "More than one set of @rules can satisfy {} for input Params({}):\n {}", - select_str(&select), + select_root_str(&select), params_str(¶ms), match_strs.join("\n "), )) diff --git a/tests/python/pants_test/engine/test_engine.py b/tests/python/pants_test/engine/test_engine.py index 4b3b2c6d684..9b9a1ca0642 100644 --- a/tests/python/pants_test/engine/test_engine.py +++ b/tests/python/pants_test/engine/test_engine.py @@ -10,7 +10,7 @@ from pants.engine.rules import RootRule, rule from pants.engine.scheduler import ExecutionError -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.util.objects import datatype from pants_test.engine.scheduler_test_base import SchedulerTestBase from pants_test.engine.util import assert_equal_with_printing, remove_locations_from_traceback @@ -36,7 +36,7 @@ def fn_raises(x): raise Exception('An exception for {}'.format(type(x).__name__)) -@rule(A, [Select(B)]) +@rule(A, [B]) def nested_raise(x): fn_raises(x) @@ -44,7 +44,7 @@ def nested_raise(x): class Fib(datatype([('val', int)])): pass -@rule(Fib, [Select(int)]) +@rule(Fib, [int]) def fib(n): if n < 2: yield Fib(n) @@ -58,7 +58,7 @@ class MyInt(datatype([('val', int)])): pass class MyFloat(datatype([('val', float)])): pass -@rule(MyFloat, [Select(MyInt)]) +@rule(MyFloat, [MyInt]) def upcast(n): yield MyFloat(float(n.val)) @@ -150,15 +150,15 @@ def fork_context_body(): def test_trace_multi(self): # Tests that when multiple distinct failures occur, they are each rendered. - @rule(D, [Select(B)]) + @rule(D, [B]) def d_from_b_nested_raise(b): fn_raises(b) - @rule(C, [Select(B)]) + @rule(C, [B]) def c_from_b_nested_raise(b): fn_raises(b) - @rule(A, [Select(C), Select(D)]) + @rule(A, [C, D]) def a_from_c_and_d(c, d): return A() @@ -227,7 +227,7 @@ def test_non_existing_root_fails_differently(self): self.assert_equal_with_printing(dedent(''' Rules with errors: 1 - (MyFloat, [Select(MyInt)], upcast()): + (MyFloat, [MyInt], upcast()): No rule was available to compute MyInt. Maybe declare it as a RootRule(MyInt)? ''').strip(), str(cm.exception) diff --git a/tests/python/pants_test/engine/test_isolated_process.py b/tests/python/pants_test/engine/test_isolated_process.py index 3e62fda72f7..b5b223add6b 100644 --- a/tests/python/pants_test/engine/test_isolated_process.py +++ b/tests/python/pants_test/engine/test_isolated_process.py @@ -16,7 +16,7 @@ FallibleExecuteProcessResult, ProcessExecutionFailure) from pants.engine.rules import RootRule, rule from pants.engine.scheduler import ExecutionError -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.util.contextutil import temporary_dir from pants.util.objects import TypeCheckError, datatype from pants_test.test_base import TestBase @@ -69,7 +69,7 @@ def argv_from_snapshot(self, snapshot): class CatExecutionRequest(datatype([('shell_cat', ShellCat), ('path_globs', PathGlobs)])): pass -@rule(Concatted, [Select(CatExecutionRequest)]) +@rule(Concatted, [CatExecutionRequest]) def cat_files_process_result_concatted(cat_exe_req): cat_bin = cat_exe_req.shell_cat cat_files_snapshot = yield Get(Snapshot, PathGlobs, cat_exe_req.path_globs) @@ -104,7 +104,7 @@ def gen_argv(self): class JavacVersionOutput(datatype([('value', text_type)])): pass -@rule(JavacVersionOutput, [Select(JavacVersionExecutionRequest)]) +@rule(JavacVersionOutput, [JavacVersionExecutionRequest]) def get_javac_version_output(javac_version_command): javac_version_proc_req = ExecuteProcessRequest( argv=javac_version_command.gen_argv(), @@ -154,7 +154,7 @@ class JavacCompileResult(datatype([ # exhaustively correct java compilation. # This rule/test should be deleted when we have more real java rules (or anything else which serves # as a suitable rule-writing example). -@rule(JavacCompileResult, [Select(JavacCompileRequest)]) +@rule(JavacCompileResult, [JavacCompileRequest]) def javac_compile_process_result(javac_compile_req): java_files = javac_compile_req.javac_sources.java_files for java_file in java_files: diff --git a/tests/python/pants_test/engine/test_mapper.py b/tests/python/pants_test/engine/test_mapper.py index 716d0bcd5ec..f6096d66b84 100644 --- a/tests/python/pants_test/engine/test_mapper.py +++ b/tests/python/pants_test/engine/test_mapper.py @@ -20,7 +20,7 @@ from pants.engine.objects import Collection from pants.engine.parser import SymbolTable from pants.engine.rules import rule -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants.engine.struct import Struct from pants.util.dirutil import safe_open from pants_test.engine.examples.parsers import JsonParser @@ -139,7 +139,7 @@ def test_duplicate_names(self): UnhydratedStructs = Collection.of(UnhydratedStruct) -@rule(UnhydratedStructs, [Select(BuildFileAddresses)]) +@rule(UnhydratedStructs, [BuildFileAddresses]) def unhydrated_structs(build_file_addresses): uhs = yield [Get(UnhydratedStruct, Address, a) for a in build_file_addresses.addresses] yield UnhydratedStructs(uhs) diff --git a/tests/python/pants_test/engine/test_rules.py b/tests/python/pants_test/engine/test_rules.py index 5d725ca035b..fccba38c75e 100644 --- a/tests/python/pants_test/engine/test_rules.py +++ b/tests/python/pants_test/engine/test_rules.py @@ -16,7 +16,7 @@ from pants.engine.mapper import AddressMapper from pants.engine.rules import (RootRule, RuleIndex, SingletonRule, _GoalProduct, _RuleVisitor, console_rule, rule) -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get from pants_test.engine.examples.parsers import JsonParser from pants_test.engine.util import (TargetTable, assert_equal_with_printing, create_scheduler, run_rule) @@ -63,7 +63,7 @@ def __repr__(self): _this_is_not_a_type = 3 -@console_rule('example', [Select(Console)]) +@console_rule('example', [Console]) def a_console_rule_generator(console): a = yield Get(A, str('a str!')) console.print_stdout(str(a)) @@ -86,7 +86,7 @@ def test_creation_fails_with_bad_declaration_type(self): class RuleGraphTest(TestBase): def test_ruleset_with_missing_product_type(self): - @rule(A, [Select(B)]) + @rule(A, [B]) def a_from_b_noop(b): pass @@ -97,21 +97,21 @@ def a_from_b_noop(b): self.assert_equal_with_printing(dedent(""" Rules with errors: 1 - (A, [Select(B)], a_from_b_noop()): + (A, [B], a_from_b_noop()): No rule was available to compute B with parameter type SubA """).strip(), str(cm.exception)) def test_ruleset_with_ambiguity(self): - @rule(A, [Select(C), Select(B)]) + @rule(A, [C, B]) def a_from_c_and_b(c, b): pass - @rule(A, [Select(B), Select(C)]) + @rule(A, [B, C]) def a_from_b_and_c(b, c): pass - @rule(D, [Select(A)]) + @rule(D, [A]) def d_from_a(a): pass @@ -129,15 +129,15 @@ def d_from_a(a): self.assert_equal_with_printing(dedent(""" Rules with errors: 1 - (D, [Select(A)], d_from_a()): - ambiguous rules for Select(A) with parameter types (B+C): - (A, [Select(B), Select(C)], a_from_b_and_c()) for (B+C) - (A, [Select(C), Select(B)], a_from_c_and_b()) for (B+C) + (D, [A], d_from_a()): + Ambiguous rules to compute A with parameter types (B+C): + (A, [B, C], a_from_b_and_c()) for (B+C) + (A, [C, B], a_from_c_and_b()) for (B+C) """).strip(), str(cm.exception)) def test_ruleset_with_rule_with_two_missing_selects(self): - @rule(A, [Select(B), Select(C)]) + @rule(A, [B, C]) def a_from_b_and_c(b, c): pass @@ -147,14 +147,14 @@ def a_from_b_and_c(b, c): self.assert_equal_with_printing(dedent(""" Rules with errors: 1 - (A, [Select(B), Select(C)], a_from_b_and_c()): + (A, [B, C], a_from_b_and_c()): No rule was available to compute B with parameter type SubA No rule was available to compute C with parameter type SubA """).strip(), str(cm.exception)) def test_ruleset_with_selector_only_provided_as_root_subject(self): - @rule(A, [Select(B)]) + @rule(A, [B]) def a_from_b(b): pass @@ -162,11 +162,11 @@ def a_from_b(b): create_scheduler(rules) def test_ruleset_with_superclass_of_selected_type_produced_fails(self): - @rule(A, [Select(B)]) + @rule(A, [B]) def a_from_b(b): pass - @rule(B, [Select(SubA)]) + @rule(B, [SubA]) def b_from_suba(suba): pass @@ -180,15 +180,15 @@ def b_from_suba(suba): create_scheduler(rules) self.assert_equal_with_printing(dedent(""" Rules with errors: 2 - (A, [Select(B)], a_from_b()): + (A, [B], a_from_b()): No rule was available to compute B with parameter type C - (B, [Select(SubA)], b_from_suba()): + (B, [SubA], b_from_suba()): No rule was available to compute SubA with parameter type C """).strip(), str(cm.exception)) def test_ruleset_with_failure_due_to_incompatible_subject_for_singleton(self): - @rule(D, [Select(C)]) + @rule(D, [C]) def d_from_c(c): pass @@ -204,7 +204,7 @@ def d_from_c(c): # This error message could note near matches like the singleton. self.assert_equal_with_printing(dedent(""" Rules with errors: 1 - (D, [Select(C)], d_from_c()): + (D, [C], d_from_c()): No rule was available to compute C with parameter type A """).strip(), str(cm.exception)) @@ -213,15 +213,15 @@ def test_not_fulfillable_duplicated_dependency(self): # If a rule depends on another rule+subject in two ways, and one of them is unfulfillable # Only the unfulfillable one should be in the errors. - @rule(B, [Select(D)]) + @rule(B, [D]) def b_from_d(d): pass - @rule(D, [Select(A), Select(SubA)]) + @rule(D, [A, SubA]) def d_from_a_and_suba(a, suba): _ = yield Get(A, C, C()) # noqa: F841 - @rule(A, [Select(C)]) + @rule(A, [C]) def a_from_c(c): pass @@ -236,15 +236,15 @@ def a_from_c(c): self.assert_equal_with_printing(dedent(""" Rules with errors: 2 - (B, [Select(D)], b_from_d()): + (B, [D], b_from_d()): No rule was available to compute D with parameter type SubA - (D, [Select(A), Select(SubA)], [Get(A, C)], d_from_a_and_suba()): + (D, [A, SubA], [Get(A, C)], d_from_a_and_suba()): No rule was available to compute A with parameter type SubA """).strip(), str(cm.exception)) def test_smallest_full_test(self): - @rule(A, [Select(SubA)]) + @rule(A, [SubA]) def a_from_suba(suba): pass @@ -259,9 +259,9 @@ def a_from_suba(suba): // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] - "Select(A) for SubA" -> {"(A, [Select(SubA)], a_from_suba()) for SubA"} + "Select(A) for SubA" -> {"(A, [SubA], a_from_suba()) for SubA"} // internal entries - "(A, [Select(SubA)], a_from_suba()) for SubA" -> {"Param(SubA)"} + "(A, [SubA], a_from_suba()) for SubA" -> {"Param(SubA)"} }""").strip(), fullgraph) def test_full_graph_for_planner_example(self): @@ -297,11 +297,11 @@ def test_full_graph_for_planner_example(self): self.assertTrue(12 < len(root_rule_lines)) # 2 lines per entry def test_smallest_full_test_multiple_root_subject_types(self): - @rule(A, [Select(SubA)]) + @rule(A, [SubA]) def a_from_suba(suba): pass - @rule(B, [Select(A)]) + @rule(B, [A]) def b_from_a(a): pass @@ -320,20 +320,20 @@ def b_from_a(a): "Select(A) for A" [color=blue] "Select(A) for A" -> {"Param(A)"} "Select(A) for SubA" [color=blue] - "Select(A) for SubA" -> {"(A, [Select(SubA)], a_from_suba()) for SubA"} + "Select(A) for SubA" -> {"(A, [SubA], a_from_suba()) for SubA"} "Select(B) for A" [color=blue] - "Select(B) for A" -> {"(B, [Select(A)], b_from_a()) for A"} + "Select(B) for A" -> {"(B, [A], b_from_a()) for A"} "Select(B) for SubA" [color=blue] - "Select(B) for SubA" -> {"(B, [Select(A)], b_from_a()) for SubA"} + "Select(B) for SubA" -> {"(B, [A], b_from_a()) for SubA"} // internal entries - "(A, [Select(SubA)], a_from_suba()) for SubA" -> {"Param(SubA)"} - "(B, [Select(A)], b_from_a()) for A" -> {"Param(A)"} - "(B, [Select(A)], b_from_a()) for SubA" -> {"(A, [Select(SubA)], a_from_suba()) for SubA"} + "(A, [SubA], a_from_suba()) for SubA" -> {"Param(SubA)"} + "(B, [A], b_from_a()) for A" -> {"Param(A)"} + "(B, [A], b_from_a()) for SubA" -> {"(A, [SubA], a_from_suba()) for SubA"} }""").strip(), fullgraph) def test_single_rule_depending_on_subject_selection(self): - @rule(A, [Select(SubA)]) + @rule(A, [SubA]) def a_from_suba(suba): pass @@ -348,14 +348,14 @@ def a_from_suba(suba): // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] - "Select(A) for SubA" -> {"(A, [Select(SubA)], a_from_suba()) for SubA"} + "Select(A) for SubA" -> {"(A, [SubA], a_from_suba()) for SubA"} // internal entries - "(A, [Select(SubA)], a_from_suba()) for SubA" -> {"Param(SubA)"} + "(A, [SubA], a_from_suba()) for SubA" -> {"Param(SubA)"} }""").strip(), subgraph) def test_multiple_selects(self): - @rule(A, [Select(SubA), Select(B)]) + @rule(A, [SubA, B]) def a_from_suba_and_b(suba, b): pass @@ -375,9 +375,9 @@ def b(): // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] - "Select(A) for SubA" -> {"(A, [Select(SubA), Select(B)], a_from_suba_and_b()) for SubA"} + "Select(A) for SubA" -> {"(A, [SubA, B], a_from_suba_and_b()) for SubA"} // internal entries - "(A, [Select(SubA), Select(B)], a_from_suba_and_b()) for SubA" -> {"(B, [], b()) for ()" "Param(SubA)"} + "(A, [SubA, B], a_from_suba_and_b()) for SubA" -> {"(B, [], b()) for ()" "Param(SubA)"} "(B, [], b()) for ()" -> {} }""").strip(), subgraph) @@ -390,15 +390,15 @@ def test_potentially_ambiguous_get(self): # This accounts for the fact that when someone uses Get (rather than Select), it's because # they intend for the Get's parameter to be consumed in the subgraph. Anything else would # be surprising. - @rule(A, [Select(SubA)]) + @rule(A, [SubA]) def a(sub_a): _ = yield Get(B, C()) # noqa: F841 - @rule(B, [Select(SubA)]) + @rule(B, [SubA]) def b_from_suba(suba): pass - @rule(SubA, [Select(C)]) + @rule(SubA, [C]) def suba_from_c(c): pass @@ -415,23 +415,23 @@ def suba_from_c(c): // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] - "Select(A) for SubA" -> {"(A, [Select(SubA)], [Get(B, C)], a()) for SubA"} + "Select(A) for SubA" -> {"(A, [SubA], [Get(B, C)], a()) for SubA"} // internal entries - "(A, [Select(SubA)], [Get(B, C)], a()) for SubA" -> {"(B, [Select(SubA)], b_from_suba()) for C" "Param(SubA)"} - "(B, [Select(SubA)], b_from_suba()) for C" -> {"(SubA, [Select(C)], suba_from_c()) for C"} - "(B, [Select(SubA)], b_from_suba()) for SubA" -> {"Param(SubA)"} - "(SubA, [Select(C)], suba_from_c()) for C" -> {"Param(C)"} + "(A, [SubA], [Get(B, C)], a()) for SubA" -> {"(B, [SubA], b_from_suba()) for C" "Param(SubA)"} + "(B, [SubA], b_from_suba()) for C" -> {"(SubA, [C], suba_from_c()) for C"} + "(B, [SubA], b_from_suba()) for SubA" -> {"Param(SubA)"} + "(SubA, [C], suba_from_c()) for C" -> {"Param(C)"} } """).strip(), subgraph, ) def test_one_level_of_recursion(self): - @rule(A, [Select(B)]) + @rule(A, [B]) def a_from_b(b): pass - @rule(B, [Select(SubA)]) + @rule(B, [SubA]) def b_from_suba(suba): pass @@ -447,15 +447,15 @@ def b_from_suba(suba): // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] - "Select(A) for SubA" -> {"(A, [Select(B)], a_from_b()) for SubA"} + "Select(A) for SubA" -> {"(A, [B], a_from_b()) for SubA"} // internal entries - "(A, [Select(B)], a_from_b()) for SubA" -> {"(B, [Select(SubA)], b_from_suba()) for SubA"} - "(B, [Select(SubA)], b_from_suba()) for SubA" -> {"Param(SubA)"} + "(A, [B], a_from_b()) for SubA" -> {"(B, [SubA], b_from_suba()) for SubA"} + "(B, [SubA], b_from_suba()) for SubA" -> {"Param(SubA)"} }""").strip(), subgraph) def test_noop_removal_in_subgraph(self): - @rule(A, [Select(C)]) + @rule(A, [C]) def a_from_c(c): pass @@ -483,7 +483,7 @@ def a(): subgraph) def test_noop_removal_full_single_subject_type(self): - @rule(A, [Select(C)]) + @rule(A, [C]) def a_from_c(c): pass @@ -510,11 +510,11 @@ def a(): fullgraph) def test_root_tuple_removed_when_no_matches(self): - @rule(A, [Select(C)]) + @rule(A, [C]) def a_from_c(c): pass - @rule(B, [Select(D), Select(A)]) + @rule(B, [D, A]) def b_from_d_and_a(d, a): pass @@ -532,12 +532,12 @@ def b_from_d_and_a(d, a): // root subject types: C, D // root entries "Select(A) for C" [color=blue] - "Select(A) for C" -> {"(A, [Select(C)], a_from_c()) for C"} + "Select(A) for C" -> {"(A, [C], a_from_c()) for C"} "Select(B) for (C+D)" [color=blue] - "Select(B) for (C+D)" -> {"(B, [Select(D), Select(A)], b_from_d_and_a()) for (C+D)"} + "Select(B) for (C+D)" -> {"(B, [D, A], b_from_d_and_a()) for (C+D)"} // internal entries - "(A, [Select(C)], a_from_c()) for C" -> {"Param(C)"} - "(B, [Select(D), Select(A)], b_from_d_and_a()) for (C+D)" -> {"(A, [Select(C)], a_from_c()) for C" "Param(D)"} + "(A, [C], a_from_c()) for C" -> {"Param(C)"} + "(B, [D, A], b_from_d_and_a()) for (C+D)" -> {"(A, [C], a_from_c()) for C" "Param(D)"} }""").strip(), fullgraph) @@ -545,11 +545,11 @@ def test_noop_removal_transitive(self): # If a noop-able rule has rules that depend on it, # they should be removed from the graph. - @rule(B, [Select(C)]) + @rule(B, [C]) def b_from_c(c): pass - @rule(A, [Select(B)]) + @rule(A, [B]) def a_from_b(b): pass @@ -576,7 +576,7 @@ def a(): subgraph) def test_get_with_matching_singleton(self): - @rule(A, [Select(SubA)]) + @rule(A, [SubA]) def a_from_suba(suba): _ = yield Get(B, C, C()) # noqa: F841 @@ -592,22 +592,22 @@ def a_from_suba(suba): // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] - "Select(A) for SubA" -> {"(A, [Select(SubA)], [Get(B, C)], a_from_suba()) for SubA"} + "Select(A) for SubA" -> {"(A, [SubA], [Get(B, C)], a_from_suba()) for SubA"} // internal entries - "(A, [Select(SubA)], [Get(B, C)], a_from_suba()) for SubA" -> {"Param(SubA)" "Singleton(B(), B)"} + "(A, [SubA], [Get(B, C)], a_from_suba()) for SubA" -> {"Param(SubA)" "Singleton(B(), B)"} }""").strip(), subgraph) def test_depends_on_multiple_one_noop(self): - @rule(B, [Select(A)]) + @rule(B, [A]) def b_from_a(a): pass - @rule(A, [Select(C)]) + @rule(A, [C]) def a_from_c(c): pass - @rule(A, [Select(SubA)]) + @rule(A, [SubA]) def a_from_suba(suba): pass @@ -624,23 +624,23 @@ def a_from_suba(suba): // root subject types: SubA // root entries "Select(B) for SubA" [color=blue] - "Select(B) for SubA" -> {"(B, [Select(A)], b_from_a()) for SubA"} + "Select(B) for SubA" -> {"(B, [A], b_from_a()) for SubA"} // internal entries - "(A, [Select(SubA)], a_from_suba()) for SubA" -> {"Param(SubA)"} - "(B, [Select(A)], b_from_a()) for SubA" -> {"(A, [Select(SubA)], a_from_suba()) for SubA"} + "(A, [SubA], a_from_suba()) for SubA" -> {"Param(SubA)"} + "(B, [A], b_from_a()) for SubA" -> {"(A, [SubA], a_from_suba()) for SubA"} }""").strip(), subgraph) def test_multiple_depend_on_same_rule(self): - @rule(B, [Select(A)]) + @rule(B, [A]) def b_from_a(a): pass - @rule(C, [Select(A)]) + @rule(C, [A]) def c_from_a(a): pass - @rule(A, [Select(SubA)]) + @rule(A, [SubA]) def a_from_suba(suba): pass @@ -657,15 +657,15 @@ def a_from_suba(suba): // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] - "Select(A) for SubA" -> {"(A, [Select(SubA)], a_from_suba()) for SubA"} + "Select(A) for SubA" -> {"(A, [SubA], a_from_suba()) for SubA"} "Select(B) for SubA" [color=blue] - "Select(B) for SubA" -> {"(B, [Select(A)], b_from_a()) for SubA"} + "Select(B) for SubA" -> {"(B, [A], b_from_a()) for SubA"} "Select(C) for SubA" [color=blue] - "Select(C) for SubA" -> {"(C, [Select(A)], c_from_a()) for SubA"} + "Select(C) for SubA" -> {"(C, [A], c_from_a()) for SubA"} // internal entries - "(A, [Select(SubA)], a_from_suba()) for SubA" -> {"Param(SubA)"} - "(B, [Select(A)], b_from_a()) for SubA" -> {"(A, [Select(SubA)], a_from_suba()) for SubA"} - "(C, [Select(A)], c_from_a()) for SubA" -> {"(A, [Select(SubA)], a_from_suba()) for SubA"} + "(A, [SubA], a_from_suba()) for SubA" -> {"Param(SubA)"} + "(B, [A], b_from_a()) for SubA" -> {"(A, [SubA], a_from_suba()) for SubA"} + "(C, [A], c_from_a()) for SubA" -> {"(A, [SubA], a_from_suba()) for SubA"} }""").strip(), subgraph) @@ -674,7 +674,7 @@ def test_get_simple(self): def a(): _ = yield Get(B, D, D()) # noqa: F841 - @rule(B, [Select(D)]) + @rule(B, [D]) def b_from_d(d): pass @@ -692,8 +692,8 @@ def b_from_d(d): "Select(A) for ()" [color=blue] "Select(A) for ()" -> {"(A, [], [Get(B, D)], a()) for ()"} // internal entries - "(A, [], [Get(B, D)], a()) for ()" -> {"(B, [Select(D)], b_from_d()) for D"} - "(B, [Select(D)], b_from_d()) for D" -> {"Param(D)"} + "(A, [], [Get(B, D)], a()) for ()" -> {"(B, [D], b_from_d()) for D"} + "(B, [D], b_from_d()) for D" -> {"Param(D)"} }""").strip(), subgraph) diff --git a/tests/python/pants_test/engine/test_scheduler.py b/tests/python/pants_test/engine/test_scheduler.py index c126388b2ca..ad49a6a5788 100644 --- a/tests/python/pants_test/engine/test_scheduler.py +++ b/tests/python/pants_test/engine/test_scheduler.py @@ -11,7 +11,7 @@ from pants.engine.rules import RootRule, UnionRule, rule, union from pants.engine.scheduler import ExecutionError -from pants.engine.selectors import Get, Params, Select +from pants.engine.selectors import Get, Params from pants.util.objects import datatype from pants_test.engine.util import assert_equal_with_printing, remove_locations_from_traceback from pants_test.test_base import TestBase @@ -29,12 +29,12 @@ def fn_raises(x): raise Exception('An exception for {}'.format(type(x).__name__)) -@rule(A, [Select(B)]) +@rule(A, [B]) def nested_raise(x): fn_raises(x) -@rule(str, [Select(A), Select(B)]) +@rule(str, [A, B]) def consumes_a_and_b(a, b): return str('{} and {}'.format(a, b)) @@ -43,7 +43,7 @@ class C(object): pass -@rule(B, [Select(C)]) +@rule(B, [C]) def transitive_b_c(c): return B() @@ -52,7 +52,7 @@ class D(datatype([('b', B)])): pass -@rule(D, [Select(C)]) +@rule(D, [C]) def transitive_coroutine_rule(c): b = yield Get(B, C, c) yield D(b) @@ -73,7 +73,7 @@ def a(self): return A() -@rule(A, [Select(UnionA)]) +@rule(A, [UnionA]) def select_union_a(union_a): return union_a.a() @@ -84,13 +84,13 @@ def a(self): return A() -@rule(A, [Select(UnionB)]) +@rule(A, [UnionB]) def select_union_b(union_b): return union_b.a() # TODO: add GetMulti testing for unions! -@rule(A, [Select(UnionWrapper)]) +@rule(A, [UnionWrapper]) def a_union_test(union_wrapper): union_a = yield Get(A, UnionBase, union_wrapper.inner) yield union_a @@ -106,7 +106,7 @@ def __init__(self, inner): self.inner = inner -@rule(A, [Select(TypeCheckFailWrapper)]) +@rule(A, [TypeCheckFailWrapper]) def a_typecheck_fail_test(wrapper): # This `yield Get(A, B, ...)` will use the `nested_raise` rule defined above, but it won't get to # the point of raising since the type check will fail at the Get. diff --git a/tests/python/pants_test/engine/test_selectors.py b/tests/python/pants_test/engine/test_selectors.py index 8d1edcb9771..b5e61fa2cc5 100644 --- a/tests/python/pants_test/engine/test_selectors.py +++ b/tests/python/pants_test/engine/test_selectors.py @@ -8,7 +8,7 @@ import unittest from builtins import object, str -from pants.engine.selectors import Get, Select +from pants.engine.selectors import Get class AClass(object): @@ -25,15 +25,6 @@ class SubBClass(BClass): pass -class SelectorsTest(unittest.TestCase): - def test_select_repr(self): - self.assert_repr("Select(AClass)", Select(AClass)) - self.assert_repr("Select(AClass, optional=True)", Select(AClass, optional=True)) - - def assert_repr(self, expected, selector): - self.assertEqual(expected, repr(selector)) - - class GetTest(unittest.TestCase): def test_create(self): # Test the equivalence of the 2-arg and 3-arg versions. diff --git a/tests/python/pants_test/init/test_extension_loader.py b/tests/python/pants_test/init/test_extension_loader.py index 6d3a844dc29..9f9698a482e 100644 --- a/tests/python/pants_test/init/test_extension_loader.py +++ b/tests/python/pants_test/init/test_extension_loader.py @@ -20,7 +20,6 @@ from pants.build_graph.build_file_aliases import BuildFileAliases from pants.build_graph.target import Target from pants.engine.rules import RootRule, rule -from pants.engine.selectors import Select from pants.goal.goal import Goal from pants.goal.task_registrar import TaskRegistrar from pants.init.extension_loader import (PluginLoadOrderError, PluginNotFound, load_backend, @@ -92,7 +91,7 @@ class WrapperType(datatype(['value'])): pass -@rule(WrapperType, [Select(RootType)]) +@rule(WrapperType, [RootType]) def example_rule(root_type): yield WrapperType(root_type.value) @@ -101,7 +100,7 @@ class PluginProduct(object): pass -@rule(PluginProduct, [Select(RootType)]) +@rule(PluginProduct, [RootType]) def example_plugin_rule(root_type): yield PluginProduct()