diff --git a/src/python/pants/task/fmt_task_mixin.py b/src/python/pants/task/fmt_task_mixin.py index 25c1d7a6aa3..d4279d36089 100644 --- a/src/python/pants/task/fmt_task_mixin.py +++ b/src/python/pants/task/fmt_task_mixin.py @@ -11,3 +11,4 @@ class FmtTaskMixin(HasSkipAndTransitiveGoalOptionsMixin): """A mixin to combine with code formatting tasks.""" goal_options_registrar_cls = SkipAndTransitiveGoalOptionsRegistrar + target_filtering_enabled = True diff --git a/src/python/pants/task/lint_task_mixin.py b/src/python/pants/task/lint_task_mixin.py index 549a5978be0..d64100b0dda 100644 --- a/src/python/pants/task/lint_task_mixin.py +++ b/src/python/pants/task/lint_task_mixin.py @@ -11,3 +11,4 @@ class LintTaskMixin(HasSkipAndTransitiveGoalOptionsMixin): """A mixin to combine with lint tasks.""" goal_options_registrar_cls = SkipAndTransitiveGoalOptionsRegistrar + target_filtering_enabled = True diff --git a/src/python/pants/task/task.py b/src/python/pants/task/task.py index 037e917a2e3..1c1ff115fa0 100644 --- a/src/python/pants/task/task.py +++ b/src/python/pants/task/task.py @@ -30,7 +30,7 @@ from pants.subsystem.subsystem_client_mixin import SubsystemClientMixin from pants.util.dirutil import safe_mkdir, safe_rm_oldest_items_in_dir from pants.util.memo import memoized_method, memoized_property -from pants.util.meta import AbstractClass +from pants.util.meta import AbstractClass, classproperty class TaskBase(SubsystemClientMixin, Optionable, AbstractClass): @@ -97,7 +97,8 @@ def _compute_stable_name(cls): @classmethod def subsystem_dependencies(cls): return (super(TaskBase, cls).subsystem_dependencies() + - (CacheSetup.scoped(cls), TargetFilter.scoped(cls), BuildInvalidator.Factory, SourceRootConfig)) + (CacheSetup.scoped(cls), BuildInvalidator.Factory, SourceRootConfig) + + ((TargetFilter.scoped(cls),) if cls.target_filtering_enabled else tuple())) @classmethod def product_types(cls): @@ -223,6 +224,17 @@ def act_transitively(self): """ return True + @classproperty + def target_filtering_enabled(cls): + """Whether this task should apply configured filters against targets. + + Tasks can override to enable target filtering (e.g. based on tags) and must + access targets via get_targets() + + :API: public + """ + return False + def get_targets(self, predicate=None): """Returns the candidate targets this task should act on. @@ -241,8 +253,14 @@ def get_targets(self, predicate=None): initial_targets = (self.context.targets(predicate) if self.act_transitively else list(filter(predicate, self.context.target_roots))) - included_targets = TargetFilter.scoped_instance(self).apply(initial_targets) - excluded_targets = set(initial_targets).difference(included_targets) + if not self.target_filtering_enabled: + return initial_targets + else: + return self._filter_targets(initial_targets) + + def _filter_targets(self, targets): + included_targets = TargetFilter.scoped_instance(self).apply(targets) + excluded_targets = set(targets).difference(included_targets) if excluded_targets: self.context.log.info("{} target(s) excluded".format(len(excluded_targets))) diff --git a/tests/python/pants_test/build_graph/test_target_filter_subsystem.py b/tests/python/pants_test/build_graph/test_target_filter_subsystem.py index 9b7cb3f8bf8..734ae7c89d4 100644 --- a/tests/python/pants_test/build_graph/test_target_filter_subsystem.py +++ b/tests/python/pants_test/build_graph/test_target_filter_subsystem.py @@ -15,6 +15,7 @@ class TestTargetFilter(TaskTestBase): class DummyTask(Task): options_scope = 'dummy' + target_filtering_enabled = True def execute(self): self.context.products.safe_create_data('task_targets', self.get_targets) diff --git a/tests/python/pants_test/task/test_task.py b/tests/python/pants_test/task/test_task.py index d86ed5dc155..d80bf34141f 100644 --- a/tests/python/pants_test/task/test_task.py +++ b/tests/python/pants_test/task/test_task.py @@ -13,6 +13,7 @@ from pants.base.exceptions import TaskError from pants.build_graph.build_file_aliases import BuildFileAliases from pants.build_graph.files import Files +from pants.build_graph.target_filter_subsystem import TargetFilter from pants.cache.cache_setup import CacheSetup from pants.option.arg_splitter import GLOBAL_SCOPE from pants.subsystem.subsystem import Subsystem @@ -149,6 +150,11 @@ def execute(self): pass +class TaskWithTargetFiltering(DummyTask): + options_scope = 'task-with-target-filtering' + target_filtering_enabled = True + + class TaskTest(TaskTestBase): _filename = 'f' @@ -650,3 +656,9 @@ def test_fingerprint_transitive(self): fp3 = self._synth_fp(cls=TaskWithTransitiveSubsystemDependencies, options_fingerprintable=option_spec) self.assertNotEqual(fp1, fp3) + + def test_target_filtering_enabled(self): + self.assertNotIn(TargetFilter.scoped(DummyTask), + DummyTask.subsystem_dependencies()) + self.assertIn(TargetFilter.scoped(TaskWithTargetFiltering), + TaskWithTargetFiltering.subsystem_dependencies())