示例#1
0
  def test_ruleset_with_failure_due_to_incompatible_subject_for_singleton(self):
    @rule(D, [C])
    def d_from_c(c):
      pass

    @rule(B, [])
    def b_singleton():
      return B()

    rules = [
      RootRule(A),
      d_from_c,
      b_singleton,
    ]

    with self.assertRaises(Exception) as cm:
      create_scheduler(rules)

    # This error message could note near matches like the singleton.
    self.assert_equal_with_printing(dedent("""
                                      Rules with errors: 1
                                        (D, [C], d_from_c()):
                                          No rule was available to compute C with parameter type A
                                      """).strip(),
                                    str(cm.exception))
示例#2
0
  def test_ruleset_with_superclass_of_selected_type_produced_fails(self):
    @rule(A, [B])
    def a_from_b(b):
      pass

    @rule(B, [SubA])
    def b_from_suba(suba):
      pass

    rules = [
      RootRule(C),
      a_from_b,
      b_from_suba,
    ]

    with self.assertRaises(Exception) as cm:
      create_scheduler(rules)
    self.assert_equal_with_printing(dedent("""
                                      Rules with errors: 2
                                        (A, [B], a_from_b()):
                                          No rule was available to compute B with parameter type C
                                        (B, [SubA], b_from_suba()):
                                          No rule was available to compute SubA with parameter type C
                                      """).strip(),
                                    str(cm.exception))
示例#3
0
  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, [D])
    def b_from_d(d):
      pass

    @rule(D, [A, SubA])
    def d_from_a_and_suba(a, suba):
      _ = yield Get(A, C, C())  # noqa: F841

    @rule(A, [C])
    def a_from_c(c):
      pass

    rules = _suba_root_rules + [
      b_from_d,
      d_from_a_and_suba,
      a_from_c,
    ]

    with self.assertRaises(Exception) as cm:
      create_scheduler(rules)

    self.assert_equal_with_printing(dedent("""
                      Rules with errors: 2
                        (B, [D], b_from_d()):
                          No rule was available to compute D with parameter type 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))
示例#4
0
  def test_ruleset_with_selector_only_provided_as_root_subject(self):
    @rule(A, [B])
    def a_from_b(b):
      pass

    rules = [RootRule(B), a_from_b]
    create_scheduler(rules)
示例#5
0
    def test_ruleset_with_ambiguity(self):
        @rule(A, [C, B])
        def a_from_c_and_b(c, b):
            pass

        @rule(A, [B, C])
        def a_from_b_and_c(b, c):
            pass

        @rule(D, [A])
        def d_from_a(a):
            pass

        rules = [
            a_from_c_and_b,
            a_from_b_and_c,
            RootRule(B),
            RootRule(C),
            # TODO: Without a rule triggering the selection of A, we don't detect ambiguity here.
            d_from_a,
        ]
        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        self.assert_equal_with_printing(
            dedent("""
                     Rules with errors: 1
                       (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))
示例#6
0
  def test_ruleset_with_ambiguity(self):
    @rule(A, [C, B])
    def a_from_c_and_b(c, b):
      pass

    @rule(A, [B, C])
    def a_from_b_and_c(b, c):
      pass

    @rule(D, [A])
    def d_from_a(a):
      pass


    rules = [
        a_from_c_and_b,
        a_from_b_and_c,
        RootRule(B),
        RootRule(C),
        # TODO: Without a rule triggering the selection of A, we don't detect ambiguity here.
        d_from_a,
      ]
    with self.assertRaises(Exception) as cm:
      create_scheduler(rules)

    self.assert_equal_with_printing(dedent("""
                     Rules with errors: 1
                       (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))
示例#7
0
    def test_ruleset_with_superclass_of_selected_type_produced_fails(self):
        @rule(A, [B])
        def a_from_b(b):
            pass

        @rule(B, [SubA])
        def b_from_suba(suba):
            pass

        rules = [
            RootRule(C),
            a_from_b,
            b_from_suba,
        ]

        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)
        self.assert_equal_with_printing(
            dedent("""
                                      Rules with errors: 2
                                        (A, [B], a_from_b()):
                                          No rule was available to compute B with parameter type C
                                        (B, [SubA], b_from_suba()):
                                          No rule was available to compute SubA with parameter type C
                                      """).strip(), str(cm.exception))
示例#8
0
    def test_ruleset_with_failure_due_to_incompatible_subject_for_singleton(
            self):
        @rule(D, [C])
        def d_from_c(c):
            pass

        @rule(B, [])
        def b_singleton():
            return B()

        rules = [
            RootRule(A),
            d_from_c,
            b_singleton,
        ]

        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        # This error message could note near matches like the singleton.
        self.assert_equal_with_printing(
            dedent("""
                                      Rules with errors: 1
                                        (D, [C], d_from_c()):
                                          No rule was available to compute C with parameter type A
                                      """).strip(), str(cm.exception))
示例#9
0
    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, [D])
        def b_from_d(d):
            pass

        @rule(D, [A, SubA])
        def d_from_a_and_suba(a, suba):
            _ = yield Get(A, C, C())  # noqa: F841

        @rule(A, [C])
        def a_from_c(c):
            pass

        rules = _suba_root_rules + [
            b_from_d,
            d_from_a_and_suba,
            a_from_c,
        ]

        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        self.assert_equal_with_printing(
            dedent("""
                      Rules with errors: 2
                        (B, [D], b_from_d()):
                          No rule was available to compute D with parameter type 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))
示例#10
0
    def test_ruleset_with_selector_only_provided_as_root_subject(self):
        @rule(A, [B])
        def a_from_b(b):
            pass

        rules = [RootRule(B), a_from_b]
        create_scheduler(rules)
示例#11
0
    def test_unreachable_rule(self):
        """Test that when one rule "shadows" another, we get an error."""
        @rule(D, [])
        def d_singleton():
            yield D()

        @rule(D, [B])
        def d_for_b(b):
            yield D()

        rules = [
            d_singleton,
            d_for_b,
            RootRule(B),
        ]

        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        self.assert_equal_with_printing(
            dedent("""
        Rules with errors: 1
          (D, [B], d_for_b()):
            Was not usable by any other @rule.
        """).strip(), str(cm.exception))
示例#12
0
  def test_ruleset_with_rule_with_two_missing_selects(self):
    rules = _suba_root_rules + [TaskRule(A, [Select(B), Select(C)], noop)]
    with self.assertRaises(ValueError) as cm:
      create_scheduler(rules)

    self.assert_equal_with_printing(dedent("""
                     Rules with errors: 1
                       (A, (Select(B), Select(C)), noop):
                         no matches for Select(B) with subject types: SubA
                         no matches for Select(C) with subject types: SubA
                     """).strip(),
      str(cm.exception))
示例#13
0
    def test_ruleset_with_rule_with_two_missing_selects(self):
        rules = _suba_root_rules + [TaskRule(A, [Select(B), Select(C)], noop)]
        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        self.assert_equal_with_printing(
            dedent("""
                     Rules with errors: 1
                       (A, (Select(B), Select(C)), noop):
                         no rule was available to compute B for subject type SubA
                         no rule was available to compute C for subject type SubA
                     """).strip(), str(cm.exception))
示例#14
0
  def test_ruleset_with_rule_with_two_missing_selects(self):
    rules = _suba_root_rules + [TaskRule(A, [Select(B), Select(C)], noop)]
    with self.assertRaises(Exception) as cm:
      create_scheduler(rules)

    self.assert_equal_with_printing(dedent("""
                     Rules with errors: 1
                       (A, (Select(B), Select(C)), noop):
                         no rule was available to compute B for subject type SubA
                         no rule was available to compute C for subject type SubA
                     """).strip(),
      str(cm.exception))
示例#15
0
    def test_ruleset_with_missing_product_type(self):
        rules = _suba_root_rules + [TaskRule(A, [Select(B)], noop)]

        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        self.assert_equal_with_printing(
            dedent("""
                     Rules with errors: 1
                       (A, [Select(B)], noop):
                         No rule was available to compute B with parameter type SubA
                     """).strip(), str(cm.exception))
示例#16
0
    def test_ruleset_with_explicit_type_constraint(self):
        @rule(Exactly(A), [Select(B)])
        def a_from_b(b):
            pass

        @rule(B, [Select(A)])
        def b_from_a(a):
            pass

        rules = _suba_root_rules + [
            a_from_b,
            b_from_a,
        ]
        create_scheduler(rules)
示例#17
0
  def test_ruleset_with_rule_with_two_missing_selects(self):
    @rule(A, [B, C])
    def a_from_b_and_c(b, c):
      pass

    rules = _suba_root_rules + [a_from_b_and_c]
    with self.assertRaises(Exception) as cm:
      create_scheduler(rules)

    self.assert_equal_with_printing(dedent("""
                     Rules with errors: 1
                       (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))
示例#18
0
    def test_ruleset_with_missing_product_type(self):
        @rule(A, [B])
        def a_from_b_noop(b):
            pass

        rules = _suba_root_rules + [a_from_b_noop]

        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        self.assert_equal_with_printing(
            dedent("""
                     Rules with errors: 1
                       (A, [B], a_from_b_noop()):
                         No rule was available to compute B with parameter type SubA
                     """).strip(), str(cm.exception))
示例#19
0
    def test_ruleset_with_rule_with_two_missing_selects(self):
        @rule(A, [B, C])
        def a_from_b_and_c(b, c):
            pass

        rules = _suba_root_rules + [a_from_b_and_c]
        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        self.assert_equal_with_printing(
            dedent("""
                     Rules with errors: 1
                       (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))
示例#20
0
  def test_trace_includes_rule_exception_traceback(self):
    rules = [
      RootRule(B),
      TaskRule(A, [Select(B)], nested_raise)
    ]

    scheduler = create_scheduler(rules)
    request = scheduler._native.new_execution_request()
    subject = B()
    scheduler.add_root_selection(request, subject, A)
    session = scheduler.new_session()
    scheduler._run_and_return_roots(session._session, request)

    trace = '\n'.join(scheduler.graph_trace(request))
    # NB removing location info to make trace repeatable
    trace = remove_locations_from_traceback(trace)

    assert_equal_with_printing(self, dedent('''
                     Computing Select(<pants_test.engine.test_scheduler.B object at 0xEEEEEEEEE>, =A)
                       Computing Task(nested_raise, <pants_test.engine.test_scheduler.B object at 0xEEEEEEEEE>, =A)
                         Throw(An exception for B)
                           Traceback (most recent call last):
                             File LOCATION-INFO, in call
                               val = func(*args)
                             File LOCATION-INFO, in nested_raise
                               fn_raises(x)
                             File LOCATION-INFO, in fn_raises
                               raise Exception('An exception for {}'.format(type(x).__name__))
                           Exception: An exception for B''').lstrip() + '\n\n', # Traces include two empty lines after.
                               trace)
示例#21
0
    def test_trace_includes_rule_exception_traceback(self):
        rules = [
            RootRule(B),
            nested_raise,
        ]

        scheduler = create_scheduler(rules)
        request = scheduler._native.new_execution_request()
        subject = B()
        scheduler.add_root_selection(request, subject, A)
        session = scheduler.new_session()
        scheduler._run_and_return_roots(session._session, request)

        trace = '\n'.join(scheduler.graph_trace(request))
        # NB removing location info to make trace repeatable
        trace = remove_locations_from_traceback(trace)

        assert_equal_with_printing(
            self,
            dedent('''
                     Computing Select(<pants_test.engine.test_scheduler.B object at 0xEEEEEEEEE>, A)
                       Computing Task(nested_raise(), <pants_test.engine.test_scheduler.B object at 0xEEEEEEEEE>, A, true)
                         Throw(An exception for B)
                           Traceback (most recent call last):
                             File LOCATION-INFO, in call
                               val = func(*args)
                             File LOCATION-INFO, in nested_raise
                               fn_raises(x)
                             File LOCATION-INFO, in fn_raises
                               raise Exception('An exception for {}'.format(type(x).__name__))
                           Exception: An exception for B''').lstrip() +
            '\n\n',  # Traces include two empty lines after.
            trace)
示例#22
0
  def test_ruleset_with_missing_product_type(self):
    @rule(A, [B])
    def a_from_b_noop(b):
      pass

    rules = _suba_root_rules + [a_from_b_noop]

    with self.assertRaises(Exception) as cm:
      create_scheduler(rules)

    self.assert_equal_with_printing(dedent("""
                     Rules with errors: 1
                       (A, [B], a_from_b_noop()):
                         No rule was available to compute B with parameter type SubA
                     """).strip(),
                                    str(cm.exception))
示例#23
0
  def test_ruleset_with_failure_due_to_incompatible_subject_for_singleton(self):
    rules = [
      RootRule(A),
      TaskRule(D, [Select(C)], noop),
      SingletonRule(B, B()),
    ]

    with self.assertRaises(ValueError) as cm:
      create_scheduler(rules)

    # This error message could note near matches like the singleton.
    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))
示例#24
0
    def test_ruleset_with_superclass_of_selected_type_produced_fails(self):
        rules = [
            RootRule(C),
            TaskRule(A, [Select(B)], noop),
            TaskRule(B, [Select(SubA)], noop)
        ]

        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)
        self.assert_equal_with_printing(
            dedent("""
                                      Rules with errors: 2
                                        (A, [Select(B)], noop):
                                          No rule was available to compute B with parameter type C
                                        (B, [Select(SubA)], noop):
                                          No rule was available to compute SubA with parameter type C
                                      """).strip(), str(cm.exception))
示例#25
0
  def test_ruleset_with_superclass_of_selected_type_produced_fails(self):
    rules = [
      RootRule(C),
      TaskRule(A, [Select(B)], noop),
      TaskRule(B, [Select(SubA)], noop)
    ]

    with self.assertRaises(Exception) as cm:
      create_scheduler(rules)
    self.assert_equal_with_printing(dedent("""
                                      Rules with errors: 2
                                        (A, (Select(B),), noop):
                                          no rule was available to compute B for subject type C
                                        (B, (Select(SubA),), noop):
                                          no rule was available to compute SubA for subject type C
                                      """).strip(),
                                    str(cm.exception))
示例#26
0
  def test_ruleset_with_superclass_of_selected_type_produced_fails(self):
    rules = [
      RootRule(C),
      TaskRule(A, [Select(B)], noop),
      TaskRule(B, [Select(SubA)], noop)
    ]

    with self.assertRaises(ValueError) as cm:
      create_scheduler(rules)
    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))
示例#27
0
    def test_ruleset_with_failure_due_to_incompatible_subject_for_singleton(
            self):
        rules = [
            RootRule(A),
            TaskRule(D, [Select(C)], noop),
            SingletonRule(B, B()),
        ]

        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        # This error message could note near matches like the singleton.
        self.assert_equal_with_printing(
            dedent("""
                                      Rules with errors: 1
                                        (D, [Select(C)], noop):
                                          No rule was available to compute C with parameter type A
                                      """).strip(), str(cm.exception))
示例#28
0
 def create_subgraph(self,
                     requested_product,
                     rules,
                     subject,
                     validate=True):
     scheduler = create_scheduler(rules + _suba_root_rules,
                                  validate=validate)
     return "\n".join(
         scheduler.rule_subgraph_visualization(type(subject),
                                               requested_product))
示例#29
0
  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.
    rules = _suba_root_rules + [
      TaskRule(B, [Select(D)], noop),
      TaskRule(D, [Select(A), Select(SubA)], noop, input_gets=[Get(A, C)]),
      TaskRule(A, [Select(SubA)], noop)
    ]

    with self.assertRaises(ValueError) as cm:
      create_scheduler(rules)

    self.assert_equal_with_printing(dedent("""
                      Rules with errors: 2
                        (B, (Select(D),), noop):
                          depends on unfulfillable (D, (Select(A), Select(SubA)), [Get(A, C)], noop) of SubA with subject types: SubA
                        (D, (Select(A), Select(SubA)), [Get(A, C)], noop):
                          depends on unfulfillable (A, (Select(SubA),), noop) of C with subject types: SubA
                      """).strip(),
        str(cm.exception))
示例#30
0
    def test_ruleset_with_ambiguity(self):
        rules = [
            TaskRule(A, [Select(C), Select(B)], noop),
            TaskRule(A, [Select(B), Select(C)], noop),
            RootRule(B),
            RootRule(C),
            # TODO: Without a rule triggering the selection of A, we don't detect ambiguity here.
            TaskRule(D, [Select(A)], noop),
        ]
        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        self.assert_equal_with_printing(
            dedent("""
                     Rules with errors: 1
                       (D, [Select(A)], noop):
                         ambiguous rules for Select(A) with parameter types (B+C):
                           (A, [Select(B), Select(C)], noop) for (B+C)
                           (A, [Select(C), Select(B)], noop) for (B+C)
                     """).strip(), str(cm.exception))
示例#31
0
    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.
        rules = _suba_root_rules + [
            TaskRule(B, [Select(D)], noop),
            TaskRule(
                D, [Select(A), Select(SubA)], noop, input_gets=[Get(A, C)]),
            TaskRule(A, [Select(C)], noop)
        ]

        with self.assertRaises(Exception) as cm:
            create_scheduler(rules)

        self.assert_equal_with_printing(
            dedent("""
                      Rules with errors: 2
                        (B, [Select(D)], noop):
                          No rule was available to compute D with parameter type SubA
                        (D, [Select(A), Select(SubA)], [Get(A, C)], noop):
                          No rule was available to compute A with parameter type SubA
                      """).strip(), str(cm.exception))
示例#32
0
 def test_ruleset_with_explicit_type_constraint(self):
   rules = _suba_root_rules + [
     TaskRule(Exactly(A), [Select(B)], noop),
     TaskRule(B, [Select(A)], noop)
   ]
   create_scheduler(rules)
示例#33
0
 def test_ruleset_with_selector_only_provided_as_root_subject(self):
   rules = [RootRule(B), TaskRule(A, [Select(B)], noop)]
   create_scheduler(rules)
示例#34
0
 def create_full_graph(self, rules, validate=True):
   scheduler = create_scheduler(rules, validate=validate)
   return "\n".join(scheduler.rule_graph_visualization())
示例#35
0
 def create_full_graph(self, rules, validate=True):
     scheduler = create_scheduler(rules, validate=validate)
     return "\n".join(scheduler.rule_graph_visualization())
示例#36
0
 def create_subgraph(self, requested_product, rules, subject, validate=True):
   scheduler = create_scheduler(rules + _suba_root_rules, validate=validate)
   return "\n".join(scheduler.rule_subgraph_visualization(type(subject), requested_product))
示例#37
0
 def test_ruleset_with_explicit_type_constraint(self):
     rules = _suba_root_rules + [
         TaskRule(Exactly(A), [Select(B)], noop),
         TaskRule(B, [Select(A)], noop)
     ]
     create_scheduler(rules)
示例#38
0
 def test_ruleset_with_selector_only_provided_as_root_subject(self):
     rules = [RootRule(B), TaskRule(A, [Select(B)], noop)]
     create_scheduler(rules)