def test_multiple(self): exactly_a_or_b = Exactly(self.A, self.B) self.assertEqual((self.A, self.B), exactly_a_or_b.types) self.assertTrue(exactly_a_or_b.satisfied_by(self.A())) self.assertTrue(exactly_a_or_b.satisfied_by(self.B())) self.assertFalse(exactly_a_or_b.satisfied_by(self.BPrime())) self.assertFalse(exactly_a_or_b.satisfied_by(self.C()))
def test_single(self): exactly_b = Exactly(self.B) self.assertEqual((self.B,), exactly_b.types) self.assertFalse(exactly_b.satisfied_by(self.A())) self.assertTrue(exactly_b.satisfied_by(self.B())) self.assertFalse(exactly_b.satisfied_by(self.BPrime())) self.assertFalse(exactly_b.satisfied_by(self.C()))
def test_ruleset_with_explicit_type_constraint(self): rules = [(Exactly(A), (Select(B), ), noop), (B, (Select(A), ), noop)] validator = RulesetValidator( RuleIndex.create(rules, tuple()), goal_to_product={}, root_subject_fns={k: lambda p: Select(p) for k in (SubA, )}) validator.validate()
def constraint_for(type_or_constraint): """Given a type or an `Exactly` constraint, returns an `Exactly` constraint.""" if isinstance(type_or_constraint, Exactly): return type_or_constraint elif isinstance(type_or_constraint, type): return Exactly(type_or_constraint) else: raise TypeError("Expected a type or constraint: got: {}".format( type_or_constraint))
def test_noop_removal_full_single_subject_type(self): rules = _suba_root_rules + [ TaskRule(Exactly(A), [Select(C)], noop), TaskRule(Exactly(A), [], noop), ] fullgraph = self.create_full_graph(RuleIndex.create(rules)) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (,), noop) of SubA"} // internal entries "(A, (,), noop) of SubA" -> {} }""").strip(), fullgraph)
def type_constraint(self): if isinstance(self.product, Exactly): return self.product elif isinstance(self.product, type): return Exactly(self.product) else: raise TypeError( "unexpected product_type type for selector: {}".format( self.product))
def test_smallest_full_test_multiple_root_subject_types(self): rules = [ (Exactly(A), (Select(SubA),), noop), (Exactly(B), (Select(A),), noop) ] select_p = lambda p: Select(p) graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=OrderedDict([(SubA, select_p), (A, select_p)])) fullgraph = graphmaker.full_graph() self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA, A,) root_rules: (Exactly(A), (Select(SubA),), noop) of SubA, (Exactly(B), (Select(A),), noop) of A, (Exactly(B), (Select(A),), noop) of SubA, SubjectIsProduct(A) (Exactly(A), (Select(SubA),), noop) of SubA => (SubjectIsProduct(SubA),) (Exactly(B), (Select(A),), noop) of A => (SubjectIsProduct(A),) (Exactly(B), (Select(A),), noop) of SubA => ((Exactly(A), (Select(SubA),), noop) of SubA,) }""").strip(), fullgraph)
def test_noop_removal_in_subgraph(self): rules = [ TaskRule(Exactly(A), [Select(C)], noop), TaskRule(Exactly(A), [], noop), SingletonRule(B, B()), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (,), noop) of SubA"} // internal entries "(A, (,), noop) of SubA" -> {} }""").strip(), subgraph)
def test_select_dependencies_multiple_field_types_all_resolvable(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(C, D,)),), noop), (B, (Select(Exactly(C, D)),), noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of SubA (B, (Select(Exactly(C, D)),), noop) of C => (SubjectIsProduct(C),) (B, (Select(Exactly(C, D)),), noop) of D => (SubjectIsProduct(D),) (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of SubA => (SubjectIsProduct(SubA), (B, (Select(Exactly(C, D)),), noop) of C, (B, (Select(Exactly(C, D)),), noop) of D,) }""").strip(), subgraph)
def test_noop_removal_full_single_subject_type(self): intrinsics = {(B, C): BoringRule(C)} rules = [ # C is provided by an intrinsic, but only if the subject is B. (Exactly(A), (Select(C),), noop), (Exactly(A), tuple(), noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, intrinsic_providers=(IntrinsicProvider(intrinsics),)), root_subject_fns=_suba_root_subject_fns) fullgraph = graphmaker.full_graph() self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (), noop) of SubA (Exactly(A), (), noop) of SubA => (,) }""").strip(), fullgraph)
def create(cls, task_entries, intrinsic_providers=(FilesystemIntrinsicRule, SnapshotIntrinsicRule)): """Creates a NodeBuilder with tasks indexed by their output type.""" # NB make tasks ordered so that gen ordering is deterministic. serializable_tasks = OrderedDict() def add_task(product_type, rule): if product_type not in serializable_tasks: serializable_tasks[product_type] = OrderedSet() serializable_tasks[product_type].add(rule) for entry in task_entries: if isinstance(entry, Rule): add_task(entry.output_product_type, entry) elif isinstance(entry, (tuple, list)) and len(entry) == 3: output_type, input_selectors, task = entry if isinstance(output_type, Exactly): constraint = output_type elif isinstance(output_type, type): constraint = Exactly(output_type) else: raise TypeError( "Unexpected product_type type {}, for rule {}".format( output_type, entry)) factory = TaskRule(tuple(input_selectors), task, output_type, constraint) for kind in constraint.types: # NB Ensure that interior types from SelectDependencies / SelectProjections work by # indexing on the list of types in the constraint. add_task(kind, factory) add_task(constraint, factory) else: raise TypeError( "Unexpected rule type: {}." " Rules either extend Rule, or are 3 elem tuples.".format( type(entry))) intrinsics = dict() for provider in intrinsic_providers: as_intrinsics = provider.as_intrinsics() duplicate_keys = [ k for k in as_intrinsics.keys() if k in intrinsics ] if duplicate_keys: key_list = '\n '.join( '{}, {}'.format(sub.__name__, prod.__name__) for sub, prod in duplicate_keys) raise ValueError( 'intrinsics provided by {} have already provided subject-type, ' 'product-type keys:\n {}'.format(provider, key_list)) intrinsics.update(as_intrinsics) return cls(serializable_tasks, intrinsics)
def test_select_dependencies_multiple_field_types_all_resolvable(self): rules = [ TaskRule(Exactly(A), [SelectDependencies(B, SubA, field_types=(C, D,))], noop), TaskRule(B, [Select(Exactly(C, D))], noop), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (SelectDependencies(B, SubA, field_types=(C, D,)),), noop) of SubA"} // internal entries "(A, (SelectDependencies(B, SubA, field_types=(C, D,)),), noop) of SubA" -> {"SubjectIsProduct(SubA)" "(B, (Select(Exactly(C, D)),), noop) of C" "(B, (Select(Exactly(C, D)),), noop) of D"} "(B, (Select(Exactly(C, D)),), noop) of C" -> {"SubjectIsProduct(C)"} "(B, (Select(Exactly(C, D)),), noop) of D" -> {"SubjectIsProduct(D)"} }""").strip(), subgraph)
def test_noop_removal_transitive(self): # If a noop-able rule has rules that depend on it, # they should be removed from the graph. rules = [ TaskRule(Exactly(B), [Select(C)], noop), TaskRule(Exactly(A), [Select(B)], noop), TaskRule(Exactly(A), [], noop), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (,), noop) of SubA"} // internal entries "(A, (,), noop) of SubA" -> {} }""").strip(), subgraph)
def test_root_tuple_removed_when_no_matches(self): rules = [ RootRule(C), RootRule(D), TaskRule(Exactly(A), [Select(C)], noop), TaskRule(Exactly(B), [Select(D), Select(A)], noop), ] fullgraph = self.create_full_graph(RuleIndex.create(rules)) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: C, D // root entries "Select(A) for C" [color=blue] "Select(A) for C" -> {"(A, (Select(C),), noop) of C"} // internal entries "(A, (Select(C),), noop) of C" -> {"SubjectIsProduct(C)"} }""").strip(), fullgraph)
def test_select_dependencies_non_matching_subselector_because_of_singleton(self): rules = [ TaskRule(Exactly(A), [SelectDependencies(B, SubA, field_types=(D,))], noop), SingletonRule(C, C()), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing(dedent(""" digraph { // empty graph }""").strip(), subgraph)
def test_noop_removal_transitive(self): # If a noop-able rule has rules that depend on it, # they should be removed from the graph. rules = [ (Exactly(B), (Select(C),), noop), (Exactly(A), (Select(B),), noop), (Exactly(A), tuple(), noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, (IntrinsicProvider({(D, C): BoringRule(C)}),)), root_subject_fns=_suba_root_subject_fns, ) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (), noop) of SubA (Exactly(A), (), noop) of SubA => (,) }""").strip(), subgraph)
def __new__(cls, output_type, value): # Validate result type. if isinstance(output_type, Exactly): constraint = output_type elif isinstance(output_type, type): constraint = Exactly(output_type) else: raise TypeError("Expected an output_type for rule; got: {}".format( output_type)) # Create. return super(SingletonRule, cls).__new__(cls, constraint, value)
def test_noop_removal_in_subgraph(self): rules = [ # C is provided by an intrinsic, but only if the subject is B. (Exactly(A), (Select(C),), noop), (Exactly(A), tuple(), noop), ] intrinsics = [ (B, C, noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, intrinsics), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (), noop) of SubA (Exactly(A), (), noop) of SubA => (,) }""").strip(), subgraph)
def test_single(self): exactly_b = Exactly(self.B) self.assertEqual((self.B, ), exactly_b.types) self.assertFalse(exactly_b.satisfied_by(self.A())) self.assertTrue(exactly_b.satisfied_by(self.B())) self.assertFalse(exactly_b.satisfied_by(self.BPrime())) self.assertFalse(exactly_b.satisfied_by(self.C()))
def create(cls, task_entries, intrinsic_entries=None, singleton_entries=None): """Creates a NodeBuilder with tasks indexed by their output type.""" intrinsic_entries = intrinsic_entries or tuple() singleton_entries = singleton_entries or tuple() # NB make tasks ordered so that gen ordering is deterministic. serializable_tasks = OrderedDict() def add_task(product_type, rule): if product_type not in serializable_tasks: serializable_tasks[product_type] = OrderedSet() serializable_tasks[product_type].add(rule) for entry in task_entries: if isinstance(entry, Rule): add_task(entry.output_product_type, entry) elif isinstance(entry, (tuple, list)) and len(entry) == 3: output_type, input_selectors, task = entry if isinstance(output_type, Exactly): constraint = output_type elif isinstance(output_type, type): constraint = Exactly(output_type) else: raise TypeError("Unexpected product_type type {}, for rule {}".format(output_type, entry)) factory = TaskRule(tuple(input_selectors), task, output_type, constraint) # TODO: The heterogenity here has some confusing implications here: # see https://github.com/pantsbuild/pants/issues/4005 for kind in constraint.types: # NB Ensure that interior types from SelectDependencies / SelectProjections work by # indexing on the list of types in the constraint. add_task(kind, factory) add_task(constraint, factory) else: raise TypeError("Unexpected rule type: {}." " Rules either extend Rule, or are 3 elem tuples.".format(type(entry))) intrinsics = dict() for output_type, input_type, func in intrinsic_entries: key = (input_type, output_type) if key in intrinsics: raise ValueError('intrinsic provided by {} has already been provided by: {}'.format( func.__name__, intrinsics[key])) intrinsics[key] = IntrinsicRule(input_type, output_type, func) singletons = dict() for output_type, func in singleton_entries: if output_type in singletons: raise ValueError('singleton provided by {} has already been provided by: {}'.format( func.__name__, singletons[output_type])) singletons[output_type] = SingletonRule(output_type, func) return cls(serializable_tasks, intrinsics, singletons)
def test_smallest_full_test(self): rules = [TaskRule(Exactly(A), [Select(SubA)], noop)] fullgraph = self.create_full_graph({SubA}, RuleIndex.create(rules)) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (Select(SubA),), noop) of SubA"} // internal entries "(A, (Select(SubA),), noop) of SubA" -> {"SubjectIsProduct(SubA)"} }""").strip(), fullgraph)
def test_noop_removal_full_single_subject_type(self): rules = [ # C is provided by an intrinsic, but only if the subject is B. (Exactly(A), (Select(C), ), noop), (Exactly(A), tuple(), noop), ] intrinsics = [ (B, C, noop), ] graphmaker = GraphMaker(RuleIndex.create(rules, intrinsics), root_subject_fns=_suba_root_subject_fns) fullgraph = graphmaker.full_graph() self.assert_equal_with_printing( dedent(""" { root_subject_types: (SubA,) root_rules: Select(A) for SubA => ((Exactly(A), (), noop) of SubA,) all_rules: (Exactly(A), (), noop) of SubA => (,) }""").strip(), fullgraph)
def test_noop_removal_full_single_subject_type(self): rules = [ # C is provided by an intrinsic, but only if the subject is B. (Exactly(A), (Select(C),), noop), (Exactly(A), tuple(), noop), ] intrinsics = [ (B, C, noop), ] fullgraph = self.create_full_graph(_suba_root_subject_types, RuleIndex.create(rules, intrinsics)) self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (,), noop) of SubA"} // internal entries "(A, (,), noop) of SubA" -> {} }""").strip(), fullgraph)
def test_select_dependencies_non_matching_subselector_because_of_intrinsic(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(D,)),), noop), ] intrinsics = [ (C, B, noop), ] subgraph = self.create_subgraph_with_intrinsics(intrinsics, A, rules, SubA(), _suba_root_subject_types) self.assert_equal_with_printing(dedent(""" digraph { // empty graph }""").strip(), subgraph)
def test_single_rule_depending_on_subject_selection(self): rules = [ (Exactly(A), (Select(SubA),), noop) ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (Select(SubA),), noop) of SubA (Exactly(A), (Select(SubA),), noop) of SubA => (SubjectIsProduct(SubA),) }""").strip(), subgraph)
def test_smallest_full_test(self): rules = [ (Exactly(A), (Select(SubA),), noop) ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns={k: lambda p: Select(p) for k in (SubA,)}) fullgraph = graphmaker.full_graph() self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (Exactly(A), (Select(SubA),), noop) of SubA (Exactly(A), (Select(SubA),), noop) of SubA => (SubjectIsProduct(SubA),) }""").strip(), fullgraph)
def test_single_rule_depending_on_subject_selection(self): rules = [TaskRule(Exactly(A), [Select(SubA)], noop)] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (Select(SubA),), noop) of SubA"} // internal entries "(A, (Select(SubA),), noop) of SubA" -> {"SubjectIsProduct(SubA)"} }""").strip(), subgraph)
def test_initial_select_projection_failure(self): rules = _suba_root_rules + [ TaskRule(Exactly(A), [SelectProjection(B, D, 'some', C)], noop), ] validator = self.create_validator({}, rules) with self.assertRaises(ValueError) as cm: validator.assert_ruleset_valid() self.assert_equal_with_printing( dedent(""" Rules with errors: 1 (A, (SelectProjection(B, D, 'some', C),), noop): no matches for Select(C) when resolving SelectProjection(B, D, 'some', C) with subject types: SubA """).strip(), str(cm.exception))
def test_secondary_select_projection_failure(self): rules = [(Exactly(A), (SelectProjection(B, D, ('some', ), C), ), noop), (C, tuple(), noop)] validator = RulesetValidator(RuleIndex.create(rules, tuple()), goal_to_product={}, root_subject_fns=_suba_root_subject_fns) with self.assertRaises(ValueError) as cm: validator.validate() self.assert_equal_with_printing( dedent(""" Rules with errors: 1 (Exactly(A), (SelectProjection(B, D, (u'some',), C),), noop): no matches for Select(B) when resolving SelectProjection(B, D, (u'some',), C) with subject types: D """).strip(), str(cm.exception))
class JvmAppAdaptor(TargetAdaptor): def __init__(self, bundles=None, **kwargs): """ :param list bundles: A list of `BundleAdaptor` objects """ super(JvmAppAdaptor, self).__init__(**kwargs) self.bundles = bundles @addressable_list(Exactly(BundleAdaptor)) def bundles(self): """The BundleAdaptors for this JvmApp.""" return self.bundles @property def field_adaptors(self): with exception_logging(logger, 'Exception in `field_adaptors` property'): field_adaptors = super(JvmAppAdaptor, self).field_adaptors if getattr(self, 'bundles', None) is None: return field_adaptors # Construct a field for the `bundles` argument. filespecs_list = [] path_globs_list = [] excluded_path_globs_list = [] for bundle in self.bundles: # Short circuit in the case of `bundles=[..., bundle(), ...]`. if not hasattr(bundle, 'fileset'): # N.B. This notice is duplicated in jvm_app.py::Bundle.__call__() for the old engine. deprecated_conditional( lambda: True, '1.2.0', 'bare bundle() without `fileset=` param', "Pass a `fileset=` parameter: `bundle(fileset=globs('*.config')`" ) logger.warn( 'Ignoring `bundle()` without `fileset` parameter.') continue base_globs = BaseGlobs.from_sources_field(bundle.fileset) filespecs_list.append(base_globs.filespecs) path_globs, excluded_path_globs = base_globs.to_path_globs( self.address.spec_path) path_globs_list.append(path_globs) excluded_path_globs_list.append(excluded_path_globs) bundles_field = BundlesField(self.address, self.bundles, filespecs_list, path_globs_list, excluded_path_globs_list) return field_adaptors + (bundles_field, )
def test_secondary_select_projection_failure(self): rules = [ (Exactly(A), (SelectProjection(B, D, ('some',), C),), noop), (C, tuple(), noop) ] validator = self.create_validator({}, tuple(), _suba_root_subject_types, rules) with self.assertRaises(ValueError) as cm: validator.assert_ruleset_valid() self.assert_equal_with_printing(dedent(""" Rules with errors: 1 (A, (SelectProjection(B, D, ('some',), C),), noop): no matches for Select(B) when resolving SelectProjection(B, D, ('some',), C) with subject types: D """).strip(), str(cm.exception))
def test_select_dependencies_non_matching_subselector_because_of_intrinsic(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(D,)),), noop), ] intrinsics = [ (C, B, noop), ] graphmaker = GraphMaker(NodeBuilder.create(rules, intrinsics), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=A) self.assert_equal_with_printing('{empty graph}', subgraph) self.assert_equal_with_printing(dedent(""" Rules with errors: 1 (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(D,)),), noop): no matches for Select(B) when resolving SelectDependencies(B, SubA, u'dependencies', field_types=(D,)) with subject types: D""").strip(), subgraph.error_message())