def test_creation_fails_with_bad_declaration_type(self): with self.assertRaises(TypeError) as cm: NodeBuilder.create([A()]) self.assertEquals( "Unexpected rule type: <class 'pants_test.engine.test_rules.A'>." " Rules either extend Rule, or are 3 elem tuples.", str(cm.exception))
def test_creation_fails_with_bad_declaration_type(self): with self.assertRaises(TypeError) as cm: NodeBuilder.create([A()]) self.assertEquals( "Unexpected rule type: <class 'pants_test.engine.test_rules.A'>." " Rules either extend Rule, or are 3 elem tuples.", str(cm.exception), )
def test_ruleset_with_with_selector_only_provided_as_root_subject(self): validator = RulesetValidator( NodeBuilder.create([(A, (Select(B),), noop)]), goal_to_product=dict(), root_subject_types=(B,) ) validator.validate()
def test_ruleset_with_explicit_type_constraint(self): rules = [(Exactly(A), (Select(B), ), noop), (B, (Select(A), ), noop)] validator = RulesetValidator(NodeBuilder.create(rules), goal_to_product=dict(), root_subject_types=tuple()) validator.validate()
def test_ruleset_with_selector_only_provided_as_root_subject(self): rules = [(A, (Select(B),), noop)] validator = RulesetValidator(NodeBuilder.create(rules, tuple()), goal_to_product={}, root_subject_fns={k: lambda p: Select(p) for k in (B,)}) validator.validate()
def test_full_graph_for_planner_example(self): symbol_table_cls = TargetTable address_mapper = AddressMapper(symbol_table_cls, JsonParser, '*.BUILD.json') tasks = create_graph_tasks(address_mapper, symbol_table_cls) + create_fs_tasks() intrinsics = create_fs_intrinsics('Let us pretend that this is a ProjectTree!') rule_index = NodeBuilder.create(tasks, intrinsics) graphmaker = GraphMaker(rule_index, root_subject_fns={k: lambda p: Select(p) for k in (Address, # TODO, use the actual fns. PathGlobs, SingleAddress, SiblingAddresses, DescendantAddresses, AscendantAddresses )}) fullgraph = graphmaker.full_graph() print('---diagnostic------') print(fullgraph.error_message()) print('/---diagnostic------') print(fullgraph) # Assert that all of the rules specified the various task fns are present declared_rules = rule_index.all_rules() rules_remaining_in_graph_strs = set(str(r.rule) for r in fullgraph.rule_dependencies.keys()) declared_rule_strings = set(str(r) for r in declared_rules) self.assertEquals(declared_rule_strings, rules_remaining_in_graph_strs )
def test_select_dependencies_recurse_with_different_type(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(C, D,)),), noop), (B, (Select(A),), noop), (C, (Select(SubA),), noop), (SubA, tuple(), 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(A),), noop) of C => ((Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of C,) (B, (Select(A),), noop) of D => ((Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of D,) (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of C => ((SubA, (), noop) of C, (B, (Select(A),), noop) of C, (B, (Select(A),), noop) of D,) (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of D => ((SubA, (), noop) of D, (B, (Select(A),), noop) of C, (B, (Select(A),), noop) of D,) (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of SubA => (SubjectIsProduct(SubA), (B, (Select(A),), noop) of C, (B, (Select(A),), noop) of D,) (SubA, (), noop) of C => (,) (SubA, (), noop) of D => (,) }""").strip(), subgraph)
def test_ruleset_with_with_selector_only_provided_as_root_subject(self): validator = RulesetValidator(NodeBuilder.create([(A, (Select(B), ), noop)]), goal_to_product=dict(), root_subject_types=(B, )) validator.validate()
def __init__(self, goals, tasks, project_tree, native, graph_lock=None): """ :param goals: A dict from a goal name to a product type. A goal is just an alias for a particular (possibly synthetic) product. :param tasks: A set of (output, input selection clause, task function) triples which is used to compute values in the product graph. :param project_tree: An instance of ProjectTree for the current build root. :param native: An instance of engine.subsystem.native.Native. :param graph_lock: A re-entrant lock to use for guarding access to the internal product Graph instance. Defaults to creating a new threading.RLock(). """ self._products_by_goal = goals self._project_tree = project_tree self._native = native self._product_graph_lock = graph_lock or threading.RLock() self._run_count = 0 # Create a handle for the ExternContext (which must be kept alive as long as this object), and # the native Scheduler. self._context = ExternContext() self._context_handle = native.new_handle(self._context) # TODO: The only (?) case where we use inheritance rather than exact type unions. has_products_constraint = TypeConstraint( self._to_id(SubclassesOf(HasProducts))) scheduler = native.lib.scheduler_create( self._context_handle, extern_key_for, extern_id_to_str, extern_val_to_str, extern_satisfied_by, extern_store_list, extern_project, extern_project_multi, self._to_key('name'), self._to_key('products'), self._to_key('default'), self._to_constraint(Address), has_products_constraint, self._to_constraint(Variants)) self._scheduler = native.gc(scheduler, native.lib.scheduler_destroy) self._execution_request = None # Validate and register all provided and intrinsic tasks. select_product = lambda product: Select(product) # TODO: This bounding of input Subject types allows for closed-world validation, but is not # strictly necessary for execution. We might eventually be able to remove it by only executing # validation below the execution roots (and thus not considering paths that aren't in use). root_selector_fns = { Address: select_product, AscendantAddresses: select_product, DescendantAddresses: select_product, PathGlobs: select_product, SiblingAddresses: select_product, SingleAddress: select_product, } intrinsics = create_fs_intrinsics( project_tree) + create_snapshot_intrinsics(project_tree) singletons = create_snapshot_singletons(project_tree) node_builder = NodeBuilder.create(tasks, intrinsics, singletons) RulesetValidator(node_builder, goals, root_selector_fns).validate() self._register_tasks(node_builder.tasks) self._register_intrinsics(node_builder.intrinsics) self._register_singletons(node_builder.singletons)
def test_ruleset_with_explicit_type_constraint(self): rules = [ (Exactly(A), (Select(B),), noop), (B, (Select(A),), noop) ] validator = RulesetValidator(NodeBuilder.create(rules, tuple()), goal_to_product={}, root_subject_fns={k: lambda p: Select(p) for k in (SubA,)}) validator.validate()
def test_fails_if_root_subject_types_empty(self): rules = [ (A, (Select(B),), noop), ] with self.assertRaises(ValueError) as cm: RulesetValidator(NodeBuilder.create(rules, tuple()), goal_to_product={}, root_subject_fns={}) self.assertEquals(dedent(""" root_subject_fns must not be empty """).strip(), str(cm.exception))
def test_ruleset_with_goal_not_produced(self): rules = [(B, (Select(SubA), ), noop)] validator = RulesetValidator(NodeBuilder.create(rules), goal_to_product={'goal-name': AGoal}, root_subject_types=tuple()) with self.assertRaises(ValueError) as cm: validator.validate() self.assertEquals( "no task for product used by goal \"goal-name\": <class 'pants_test.engine.test_rules.AGoal'>", str(cm.exception))
def test_ruleset_with_goal_not_produced(self): rules = [(B, (Select(SubA),), noop)] validator = RulesetValidator( NodeBuilder.create(rules), goal_to_product={"goal-name": AGoal}, root_subject_types=tuple() ) with self.assertRaises(ValueError) as cm: validator.validate() self.assertEquals( "no task for product used by goal \"goal-name\": <class 'pants_test.engine.test_rules.AGoal'>", str(cm.exception), )
def test_ruleset_with_missing_product_type(self): rules = [(A, (Select(B),), noop)] validator = RulesetValidator(NodeBuilder.create(rules, tuple()), goal_to_product={}, root_subject_fns={k: lambda p: Select(p) for k in (SubA,)}) with self.assertRaises(ValueError) as cm: validator.validate() self.assert_equal_with_printing(dedent(""" Rules with errors: 1 (A, (Select(B),), noop): no matches for Select(B) with subject types: SubA """).strip(), str(cm.exception))
def test_ruleset_with_missing_product_type(self): rules = [(A, (Select(B), ), noop)] validator = RulesetValidator(NodeBuilder.create(rules), goal_to_product=dict(), root_subject_types=tuple()) with self.assertRaises(ValueError) as cm: validator.validate() self.assertEquals( dedent(""" Found 1 rules with errors: (A, (Select(B),), noop) There is no producer of Select(B) """).strip(), str(cm.exception))
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_ruleset_with_goal_not_produced(self): # The graph is complete, but the goal 'goal-name' requests A, # which is not produced by any rule. rules = [ (B, (Select(SubA),), noop) ] validator = RulesetValidator(NodeBuilder.create(rules, tuple()), goal_to_product={'goal-name': AGoal}, root_subject_fns={k: lambda p: Select(p) for k in (SubA,)}) with self.assertRaises(ValueError) as cm: validator.validate() self.assert_equal_with_printing("no task for product used by goal \"goal-name\": AGoal", str(cm.exception))
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_ruleset_with_missing_product_type(self): rules = [(A, (Select(B),), noop)] validator = RulesetValidator(NodeBuilder.create(rules), goal_to_product=dict(), root_subject_types=tuple()) with self.assertRaises(ValueError) as cm: validator.validate() self.assertEquals( dedent( """ Found 1 rules with errors: (A, (Select(B),), noop) There is no producer of Select(B) """ ).strip(), str(cm.exception), )
def test_select_literal(self): literally_a = A() rules = [ (B, (SelectLiteral(literally_a, A),), noop) ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=B) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (B, (SelectLiteral(A(), A),), noop) of SubA (B, (SelectLiteral(A(), A),), noop) of SubA => (Literal(A(), A),) }""").strip(), subgraph)
def test_initial_select_projection_failure(self): rules = [ (Exactly(A), (SelectProjection(B, D, ('some',), C),), noop), ] validator = RulesetValidator(NodeBuilder.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(C) when resolving SelectProjection(B, D, (u'some',), C) with subject types: SubA """).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())
def test_select_dependencies_with_subject_as_first_subselector(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(D,)),), noop), (B, (Select(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, field_types=(D,)),), noop) of SubA (B, (Select(D),), noop) of D => (SubjectIsProduct(D),) (Exactly(A), (SelectDependencies(B, SubA, field_types=(D,)),), noop) of SubA => (SubjectIsProduct(SubA), (B, (Select(D),), noop) of D,) }""").strip(), subgraph)
def test_depends_on_multiple_one_noop(self): rules = [ (B, (Select(A),), noop), (A, (Select(C),), noop), (A, (Select(SubA),), noop) ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=B) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (B, (Select(A),), noop) of SubA (A, (Select(SubA),), noop) of SubA => (SubjectIsProduct(SubA),) (B, (Select(A),), noop) of SubA => ((A, (Select(SubA),), noop) of SubA,) }""").strip(), subgraph)
def __init__(self, goals, tasks, project_tree, graph_lock=None, inline_nodes=True, graph_validator=None): """ :param goals: A dict from a goal name to a product type. A goal is just an alias for a particular (possibly synthetic) product. :param tasks: A set of (output, input selection clause, task function) triples which is used to compute values in the product graph. :param project_tree: An instance of ProjectTree for the current build root. :param graph_lock: A re-entrant lock to use for guarding access to the internal ProductGraph instance. Defaults to creating a new threading.RLock(). :param inline_nodes: Whether to inline execution of `inlineable` Nodes. This improves performance, but can make debugging more difficult because the entire execution history is not recorded in the ProductGraph. :param graph_validator: A validator that runs over the entire graph after every scheduling attempt. Very expensive, very experimental. """ self._products_by_goal = goals self._project_tree = project_tree self._node_builder = NodeBuilder.create(tasks) self._graph_validator = graph_validator self._product_graph = ProductGraph() self._product_graph_lock = graph_lock or threading.RLock() self._inline_nodes = inline_nodes select_product = lambda product: Select(product) select_dep_addrs = lambda product: SelectDependencies( product, Addresses, field_types=(Address, )) self._root_selector_fns = { Address: select_product, PathGlobs: select_product, SingleAddress: select_dep_addrs, SiblingAddresses: select_dep_addrs, AscendantAddresses: select_dep_addrs, DescendantAddresses: select_dep_addrs, } RulesetValidator(self._node_builder, goals, self._root_selector_fns.keys()).validate()
def test_ruleset_with_superclass_of_selected_type_produced_fails(self): rules = [ (A, (Select(B),), noop), (B, (Select(SubA),), noop) ] validator = RulesetValidator(NodeBuilder.create(rules, tuple()), goal_to_product={}, root_subject_fns={k: lambda p: Select(p) for k in (C,)}) with self.assertRaises(ValueError) as cm: validator.validate() self.assert_equal_with_printing(dedent(""" Rules with errors: 2 (A, (Select(B),), noop): depends on unfulfillable (B, (Select(SubA),), noop) of C with subject types: C (B, (Select(SubA),), noop): no matches for Select(SubA) with subject types: C """).strip(), str(cm.exception))
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_successful_when_one_field_type_is_unfulfillable(self): # NB We may want this to be a warning, since it may not be intentional rules = [ (B, (Select(SubA),), noop), (D, (Select(Exactly(B)), SelectDependencies(B, SubA, field_types=(SubA, C))), noop) ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.generate_subgraph(SubA(), requested_product=D) self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (D, (Select(Exactly(B)), SelectDependencies(B, SubA, u'dependencies', field_types=(SubA, C,))), noop) of SubA (B, (Select(SubA),), noop) of SubA => (SubjectIsProduct(SubA),) (D, (Select(Exactly(B)), SelectDependencies(B, SubA, u'dependencies', field_types=(SubA, C,))), noop) of SubA => ((B, (Select(SubA),), noop) of SubA, SubjectIsProduct(SubA), (B, (Select(SubA),), noop) of SubA,) }""").strip(), subgraph)
def test_multiple_depend_on_same_rule(self): rules = [ (B, (Select(A),), noop), (C, (Select(A),), noop), (A, (Select(SubA),), noop) ] graphmaker = GraphMaker(NodeBuilder.create(rules, tuple()), root_subject_fns=_suba_root_subject_fns) subgraph = graphmaker.full_graph() self.assert_equal_with_printing(dedent(""" { root_subject_types: (SubA,) root_rules: (A, (Select(SubA),), noop) of SubA, (B, (Select(A),), noop) of SubA, (C, (Select(A),), noop) of SubA (A, (Select(SubA),), noop) of SubA => (SubjectIsProduct(SubA),) (B, (Select(A),), noop) of SubA => ((A, (Select(SubA),), noop) of SubA,) (C, (Select(A),), noop) of SubA => ((A, (Select(SubA),), noop) of SubA,) }""").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 __init__(self, goals, tasks, project_tree, graph_lock=None, inline_nodes=True, graph_validator=None): """ :param goals: A dict from a goal name to a product type. A goal is just an alias for a particular (possibly synthetic) product. :param tasks: A set of (output, input selection clause, task function) triples which is used to compute values in the product graph. :param project_tree: An instance of ProjectTree for the current build root. :param graph_lock: A re-entrant lock to use for guarding access to the internal ProductGraph instance. Defaults to creating a new threading.RLock(). :param inline_nodes: Whether to inline execution of `inlineable` Nodes. This improves performance, but can make debugging more difficult because the entire execution history is not recorded in the ProductGraph. :param graph_validator: A validator that runs over the entire graph after every scheduling attempt. Very expensive, very experimental. """ self._products_by_goal = goals self._project_tree = project_tree self._node_builder = NodeBuilder.create(tasks) self._graph_validator = graph_validator self._product_graph = ProductGraph() self._product_graph_lock = graph_lock or threading.RLock() self._inline_nodes = inline_nodes select_product = lambda product: Select(product) select_dep_addrs = lambda product: SelectDependencies(product, Addresses, field_types=(Address,)) self._root_selector_fns = { Address: select_product, PathGlobs: select_product, SingleAddress: select_dep_addrs, SiblingAddresses: select_dep_addrs, AscendantAddresses: select_dep_addrs, DescendantAddresses: select_dep_addrs, } RulesetValidator(self._node_builder, goals, self._root_selector_fns.keys()).validate()
def test_ruleset_with_failure_due_to_incompatible_subject_for_intrinsic(self): rules = [ (D, (Select(C),), noop) ] intrinsics = [ (B, C, noop), ] validator = RulesetValidator(NodeBuilder.create(rules, intrinsics), goal_to_product={}, root_subject_fns={k: lambda p: Select(p) for k in (A,)}) with self.assertRaises(ValueError) as cm: validator.validate() self.assert_equal_with_printing(dedent(""" Rules with errors: 1 (D, (Select(C),), noop): no matches for Select(C) with subject types: A """).strip(), str(cm.exception))
def test_select_dependencies_with_matching_intrinsic(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(C,)),), 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), (SelectDependencies(B, SubA, u'dependencies', field_types=(C,)),), noop) of SubA (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C,)),), noop) of SubA => (SubjectIsProduct(SubA), IntrinsicRule(noop) of C,) IntrinsicRule(noop) of C => (,) }""").strip(), subgraph)
def test_ruleset_unreachable_due_to_product_of_select_dependencies(self): rules = [ (A, (SelectDependencies(B, SubA, field_types=(D,)),), noop), ] intrinsics = [ (B, C, noop), ] validator = RulesetValidator(NodeBuilder.create(rules, intrinsics), goal_to_product={}, root_subject_fns={k: lambda p: Select(p) for k in (A,)}) with self.assertRaises(ValueError) as cm: validator.validate() self.assert_equal_with_printing(dedent(""" Rules with errors: 1 (A, (SelectDependencies(B, SubA, u'dependencies', field_types=(D,)),), noop): Unreachable with subject types: Any """).strip(), str(cm.exception))
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_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 test_select_dependencies_multiple_field_types_all_resolvable_with_deps(self): rules = [ (Exactly(A), (SelectDependencies(B, SubA, field_types=(C, D,)),), noop), # for the C type, it'll just be a literal, but for D, it'll traverse one more edge (B, (Select(C),), noop), (C, (Select(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(C),), noop) of C => (SubjectIsProduct(C),) (B, (Select(C),), noop) of D => ((C, (Select(D),), noop) of D,) (C, (Select(D),), noop) of D => (SubjectIsProduct(D),) (Exactly(A), (SelectDependencies(B, SubA, u'dependencies', field_types=(C, D,)),), noop) of SubA => (SubjectIsProduct(SubA), (B, (Select(C),), noop) of C, (B, (Select(C),), noop) of D,) }""").strip(), subgraph)