Beispiel #1
0
 def test_constructor_with_variables(self):
     """The order must not change when the parameters are variables."""
     l_op = PedestriansCrossingRoad()
     r_op = DriversAwaitingGreenLightVar()
     operation = LessThan(l_op, r_op)
     eq_(l_op, operation.master_operand)
     eq_(r_op, operation.slave_operand)
Beispiel #2
0
    def test_constructor_with_constant_before_variable(self):
        """
        The order *must* change when the first parameter is a constant and
        the second is a variable.

        """
        l_op = Number(2)
        r_op = PedestriansCrossingRoad()
        operation = GreaterThan(l_op, r_op)
        eq_(r_op, operation.master_operand)
        eq_(l_op, operation.slave_operand)
Beispiel #3
0
    def test_constructor_with_variable_before_constant(self):
        """
        The order must not change when the first parameter is a variable and
        the second is a constant.

        """
        l_op = PedestriansCrossingRoad()
        r_op = Number(2)
        operation = LessThan(l_op, r_op)
        eq_(l_op, operation.master_operand)
        eq_(r_op, operation.slave_operand)
Beispiel #4
0
    def test_mixed_evaluation(self):
        operation = NotEqual(PedestriansCrossingRoad(),
                             Set(String("gustavo"), String("carla")))

        # Other people:
        context = {'pedestrians_crossroad': ("liliana", "carlos")}
        ok_(operation(context))

        # The same people:
        context = {'pedestrians_crossroad': ("gustavo", "carla")}
        assert_false(operation(context))
Beispiel #5
0
    def test_equivalent(self):
        """Two conjunctions are equivalent if they have the same operands."""
        op1 = And(BoolVar(), PedestriansCrossingRoad())
        op2 = And(PedestriansCrossingRoad(), BoolVar())
        op3 = And(DriversAwaitingGreenLightVar(), BoolVar())

        op1.check_equivalence(op2)
        op2.check_equivalence(op1)

        assert_raises(AssertionError, op1.check_equivalence, op3)
        assert_raises(AssertionError, op2.check_equivalence, op3)
        assert_raises(AssertionError, op3.check_equivalence, op1)
        assert_raises(AssertionError, op3.check_equivalence, op2)

        ok_(op1 == op2)
        ok_(op2 == op1)
        ok_(op1 != op3)
        ok_(op2 != op3)
        ok_(op3 != op1)
        ok_(op3 != op2)
Beispiel #6
0
 def test_adding_grammar(self):
     """It should be possible to add grammars after instantiation."""
     castilian_grammar = Grammar(decimal_separator=",",
                                 thousands_separator=".")
     mgr = EvaluableParseManager(self.symbol_table, Grammar())
     mgr.add_parser("es", castilian_grammar)
     parse_tree = mgr.parse(u'tráfico:peatones_cruzando_calle <= 3,00',
                            "es")
     expected_tree = EvaluableParseTree(
         LessEqual(PedestriansCrossingRoad(), Number(3.0)))
     eq_(parse_tree, expected_tree)
Beispiel #7
0
 def test_parsing_with_localized_grammars(self):
     castilian_grammar = Grammar(decimal_separator=",",
                                 thousands_separator=".")
     mgr = EvaluableParseManager(self.symbol_table,
                                 Grammar(),
                                 es=castilian_grammar)
     parse_tree = mgr.parse(u"tráfico:peatones_cruzando_calle <= 3,00",
                            "es")
     expected_tree = EvaluableParseTree(
         LessEqual(PedestriansCrossingRoad(), Number(3.0)))
     eq_(parse_tree, expected_tree)
Beispiel #8
0
    def test_mixed_arguments(self):
        l_op = PedestriansCrossingRoad()
        r_op = Number(2)
        operation = GreaterEqual(l_op, r_op)

        # |{"carla", "yolmary", "manuel"}| > 2   <=>   3 > 2
        context = {'pedestrians_crossroad': ("carla", "yolmary", "manuel")}
        ok_(operation(context))

        # |{"carla"}| > 2   <=>   1 > 2
        context = {'pedestrians_crossroad': ("carla", )}
        assert_false(operation(context))
Beispiel #9
0
    def test_mixed_arguments(self):
        l_op = PedestriansCrossingRoad()
        r_op = Number(2)
        operation = LessEqual(l_op, r_op)

        # |{"carla"}| < 2   <=>   1 < 2
        context = {'pedestrians_crossroad': ("carla", )}
        ok_(operation(context))

        # |{"carla", "carlos", "liliana"}| < 2   <=>   1 < 2
        context = {'pedestrians_crossroad': ("carla", "carlos", "liliana")}
        assert_false(operation(context))
Beispiel #10
0
 def test_operation(self):
     """Operations are valid evaluable parse trees."""
     operation = And(PedestriansCrossingRoad(),
                     DriversAwaitingGreenLightVar())
     tree = EvaluableParseTree(operation)
     # True
     context = {
         'pedestrians_crossroad': ("gustavo", "carla"),
         'drivers_trafficlight': ("andreina", "juan")
     }
     ok_(tree(context))
     # False
     context = {'pedestrians_crossroad': (), 'drivers_traffic_light': ()}
     assert_false(tree(context))
Beispiel #11
0
    def test_variable_evaluation(self):
        item = NumVar()
        set_ = PedestriansCrossingRoad()
        operation = BelongsTo(item, set_)

        # 4 ∈ {"madrid", 4}
        context = {'num': 4, 'pedestrians_crossroad': ("madrid", 4)}
        ok_(operation(context))

        # 4 ∈ {"madrid", "paris", "london"}
        context = {
            'num': 4,
            'pedestrians_crossroad': ("madrid", "paris", "london")
        }
        assert_false(operation(context))
Beispiel #12
0
    def test_two_variables(self):
        l_op = PedestriansCrossingRoad()
        r_op = NumVar()
        operation = GreaterEqual(l_op, r_op)

        # |{"carla", "yolmary"}| > 1   <=>   2 > 1
        context = {
            'pedestrians_crossroad': ("carla", "yolmary"),
            'num': 1,
        }
        ok_(operation(context))

        # |{"carla", "carlos"}| > 3   <=>   2 > 3
        context = {
            'pedestrians_crossroad': ("carla", "carlos"),
            'num': 3,
        }
        assert_false(operation(context))
Beispiel #13
0
    def test_parsing_with_defined_grammar_but_no_available_translations(self):
        """
        When an expression is written in an supported grammar but there are no
        translated bindings, the default names must be used along with the
        custom grammar.

        """
        french_grammar = Grammar(decimal_separator=",",
                                 thousands_separator=".")
        mgr = EvaluableParseManager(self.symbol_table,
                                    Grammar(),
                                    fr=french_grammar)
        # French grammar is not supported:
        parse_tree = mgr.parse("traffic:pedestrians_crossing_road <= 3,0",
                               "fr")
        expected_tree = EvaluableParseTree(
            LessEqual(PedestriansCrossingRoad(), Number(3)))
        eq_(parse_tree, expected_tree)
Beispiel #14
0
    def test_variable_evaluation(self):
        subset = DriversAwaitingGreenLightVar()
        set_ = PedestriansCrossingRoad()
        operation = IsSubset(subset, set_)

        # {"carla"} ⊂ {"carla", "andreina"}
        context = {
            'drivers_trafficlight': ("carla", ),
            'pedestrians_crossroad': ("andreina", "carla")
        }
        ok_(operation(context))

        # {"liliana", "carlos"} ⊂ {"manuel", "yolmary", "carla"}
        context = {
            'drivers_trafficlight': ("liliana", "carlos"),
            'pedestrians_crossroad': ("manuel", "yolmary", "carla")
        }
        assert_false(operation(context))
Beispiel #15
0
    def test_variables_evaluation(self):
        operation = NotEqual(PedestriansCrossingRoad(),
                             DriversAwaitingGreenLightVar())

        # The pedestrians are different from the drivers... That's my universe!
        context = {
            'pedestrians_crossroad': ("gustavo", "carla"),
            'drivers_trafficlight': ("liliana", "carlos")
        }
        ok_(operation(context))

        # The pedestrians awaiting the green light to cross the street are
        # the same drivers... Must be a parallel universe!
        context = {
            'pedestrians_crossroad': ("gustavo", "carla"),
            'drivers_trafficlight': ("carla", "gustavo")
        }
        assert_false(operation(context))
Beispiel #16
0
    def test_two_variables(self):
        l_op = PedestriansCrossingRoad()
        r_op = NumVar()
        operation = LessEqual(l_op, r_op)

        # |{"carla"}| < 2   <=>   1 < 2
        context = {
            'pedestrians_crossroad': ("carla", ),
            'num': 2,
        }
        ok_(operation(context))

        # |{"carla", "carlos"}| < 1   <=>   2 < 1
        context = {
            'pedestrians_crossroad': ("carla", "carlos"),
            'num': 1,
        }
        assert_false(operation(context))
Beispiel #17
0
    def test_parsing_with_undefined_grammar_and_no_translated_bindings(self):
        """
        When an expression is written in an unsupported grammar, a parser
        based on the generic grammar must be created and used.

        If there are no translated bindings, the default names must be used.

        """
        log_handler = LoggingHandlerFixture()
        mgr = EvaluableParseManager(self.symbol_table, Grammar())
        # French grammar is not supported:
        parse_tree = mgr.parse("traffic:pedestrians_crossing_road <= 3.0",
                               "fr")
        expected_tree = EvaluableParseTree(
            LessEqual(PedestriansCrossingRoad(), Number(3)))
        eq_(parse_tree, expected_tree)
        # Checking the log:
        info = "Generated parser for unknown grammar %s" % repr('fr')
        ok_(info in log_handler.handler.messages['info'])
        log_handler.undo()
Beispiel #18
0
    def test_parsing_with_undefined_grammar_but_available_translations(self):
        """
        When an expression is written in an unsupported grammar, a parser
        based on the generic grammar must be created and used.

        The respective translated bindings must be used if available.

        """
        log_handler = LoggingHandlerFixture()
        mgr = EvaluableParseManager(self.symbol_table, Grammar())
        # Castilian grammar is not supported:
        parse_tree = mgr.parse(u"tráfico:peatones_cruzando_calle <= 3.0", "es")
        expected_tree = EvaluableParseTree(
            LessEqual(PedestriansCrossingRoad(), Number(3)))
        eq_(parse_tree, expected_tree)
        # Checking the log:
        info = "Generated parser for unknown grammar %s" % repr(u'es')

        ok_(info in log_handler.handler.messages['info'])
        log_handler.undo()
Beispiel #19
0
    def test_equivalence(self):
        tree1 = EvaluableParseTree(BoolVar())
        tree2 = EvaluableParseTree(BoolVar())
        tree3 = EvaluableParseTree(PedestriansCrossingRoad())
        tree4 = ConvertibleParseTree(PlaceholderVariable("my_variable"))

        ok_(tree1 == tree2)
        ok_(tree2 == tree1)

        ok_(tree1 != None)
        ok_(tree1 != tree3)
        ok_(tree1 != tree4)
        ok_(tree2 != tree3)
        ok_(tree2 != tree4)
        ok_(tree3 != tree1)
        ok_(tree3 != tree2)
        ok_(tree3 != tree4)
        ok_(tree4 != tree1)
        ok_(tree4 != tree2)
        ok_(tree4 != tree3)
Beispiel #20
0
    def test_equivalent(self):
        """
        Two negation operations are equivalent if they evaluate the same
        operand.

        """
        op1 = Not(BoolVar())
        op2 = Not(BoolVar())
        op3 = Not(PedestriansCrossingRoad())

        op1.check_equivalence(op2)
        op2.check_equivalence(op1)

        assert_raises(AssertionError, op1.check_equivalence, op3)
        assert_raises(AssertionError, op2.check_equivalence, op3)
        assert_raises(AssertionError, op3.check_equivalence, op1)
        assert_raises(AssertionError, op3.check_equivalence, op2)

        ok_(op1 == op2)
        ok_(op2 == op1)
        ok_(op1 != op3)
        ok_(op2 != op3)
        ok_(op3 != op1)
        ok_(op3 != op2)
Beispiel #21
0
class TestEvaluableParseManager(object):
    """
    Tests for the :class:`EvaluableParseManager` with caching disabled.

    """

    # A symbol table to be used across the tests:
    symbol_table = SymbolTable(
        "root",
        (
            Bind("boolean", BoolVar(), es="booleano"),
            Bind("message", String("Hello world"), es="mensaje"),
            Bind("foo", PermissiveFunction, es="fulano"),
        ),
        SymbolTable("traffic", (
            Bind("traffic_light", TrafficLightVar(), es=u"semáforo"),
            Bind("pedestrians_crossing_road",
                 PedestriansCrossingRoad(),
                 es="peatones_cruzando_calle"),
            Bind("drivers_awaiting_green",
                 DriversAwaitingGreenLightVar(),
                 es="conductores_esperando_verde"),
            Bind("traffic_violation", TrafficViolationFunc, es=u"infracción"),
        ),
                    es=u"tráfico"),
    )

    def test_parsing_with_no_localized_grammars(self):
        mgr = EvaluableParseManager(self.symbol_table, Grammar())
        parse_tree1 = mgr.parse('message == "2009-07-13"')
        parse_tree2 = mgr.parse('message == "2009-07-13"', None)
        expected_tree = EvaluableParseTree(
            Equal(String("Hello world"), String("2009-07-13")))
        eq_(parse_tree1, parse_tree2)
        eq_(parse_tree1, expected_tree)

    def test_parsing_with_localized_grammars(self):
        castilian_grammar = Grammar(decimal_separator=",",
                                    thousands_separator=".")
        mgr = EvaluableParseManager(self.symbol_table,
                                    Grammar(),
                                    es=castilian_grammar)
        parse_tree = mgr.parse(u"tráfico:peatones_cruzando_calle <= 3,00",
                               "es")
        expected_tree = EvaluableParseTree(
            LessEqual(PedestriansCrossingRoad(), Number(3.0)))
        eq_(parse_tree, expected_tree)

    def test_parsing_with_undefined_grammar_but_available_translations(self):
        """
        When an expression is written in an unsupported grammar, a parser
        based on the generic grammar must be created and used.

        The respective translated bindings must be used if available.

        """
        log_handler = LoggingHandlerFixture()
        mgr = EvaluableParseManager(self.symbol_table, Grammar())
        # Castilian grammar is not supported:
        parse_tree = mgr.parse(u"tráfico:peatones_cruzando_calle <= 3.0", "es")
        expected_tree = EvaluableParseTree(
            LessEqual(PedestriansCrossingRoad(), Number(3)))
        eq_(parse_tree, expected_tree)
        # Checking the log:
        info = "Generated parser for unknown grammar %s" % repr(u'es')

        ok_(info in log_handler.handler.messages['info'])
        log_handler.undo()

    def test_parsing_with_undefined_grammar_and_no_translated_bindings(self):
        """
        When an expression is written in an unsupported grammar, a parser
        based on the generic grammar must be created and used.

        If there are no translated bindings, the default names must be used.

        """
        log_handler = LoggingHandlerFixture()
        mgr = EvaluableParseManager(self.symbol_table, Grammar())
        # French grammar is not supported:
        parse_tree = mgr.parse("traffic:pedestrians_crossing_road <= 3.0",
                               "fr")
        expected_tree = EvaluableParseTree(
            LessEqual(PedestriansCrossingRoad(), Number(3)))
        eq_(parse_tree, expected_tree)
        # Checking the log:
        info = "Generated parser for unknown grammar %s" % repr('fr')
        ok_(info in log_handler.handler.messages['info'])
        log_handler.undo()

    def test_parsing_with_defined_grammar_but_no_available_translations(self):
        """
        When an expression is written in an supported grammar but there are no
        translated bindings, the default names must be used along with the
        custom grammar.

        """
        french_grammar = Grammar(decimal_separator=",",
                                 thousands_separator=".")
        mgr = EvaluableParseManager(self.symbol_table,
                                    Grammar(),
                                    fr=french_grammar)
        # French grammar is not supported:
        parse_tree = mgr.parse("traffic:pedestrians_crossing_road <= 3,0",
                               "fr")
        expected_tree = EvaluableParseTree(
            LessEqual(PedestriansCrossingRoad(), Number(3)))
        eq_(parse_tree, expected_tree)

    def test_adding_grammar(self):
        """It should be possible to add grammars after instantiation."""
        castilian_grammar = Grammar(decimal_separator=",",
                                    thousands_separator=".")
        mgr = EvaluableParseManager(self.symbol_table, Grammar())
        mgr.add_parser("es", castilian_grammar)
        parse_tree = mgr.parse(u'tráfico:peatones_cruzando_calle <= 3,00',
                               "es")
        expected_tree = EvaluableParseTree(
            LessEqual(PedestriansCrossingRoad(), Number(3.0)))
        eq_(parse_tree, expected_tree)

    def test_adding_existing_grammar(self):
        """There can't be duplicate/overlapped parsers."""
        mgr = EvaluableParseManager(self.symbol_table, Grammar(), es=Grammar())
        assert_raises(GrammarError, mgr.add_parser, "es", Grammar())

    def test_evaluating_expressions(self):
        """Managers should be able to evaluate the expressions too."""
        mgr = EvaluableParseManager(self.symbol_table, Grammar())
        context = {'pedestrians_crossroad': (u"gustavo", u"carla")}
        evaluation1 = mgr.evaluate("traffic:pedestrians_crossing_road <= 3",
                                   None, context)
        evaluation2 = mgr.evaluate(
            u'"carla" ∈ traffic:pedestrians_crossing_road', None, context)
        evaluation3 = mgr.evaluate("traffic:pedestrians_crossing_road > 2",
                                   None, context)
        ok_(evaluation1)
        ok_(evaluation2)
        assert_false(evaluation3)
Beispiel #22
0
class TestEvaluableParser(object):
    """Tests for the evaluable parser."""

    global_objects = {
        'bool': BoolVar(),
        'message': String("Hello world"),
        'foo': PermissiveFunction,
    }

    traffic_objects = {
        'traffic_light': TrafficLightVar(),
        'pedestrians_crossing_road': PedestriansCrossingRoad(),
        'drivers_awaiting_green_light': DriversAwaitingGreenLightVar(),
        'traffic_violation': TrafficViolationFunc,
    }

    root_namespace = Namespace(global_objects, {
        'traffic': Namespace(traffic_objects),
    })

    parser = EvaluableParser(Grammar(), root_namespace)

    # Tests for the parse action that makes the variables

    def test_existing_variable_without_namespace(self):
        parse_tree = self.parser("~ bool")
        eq_(parse_tree.root_node, Not(self.global_objects['bool']))

    def test_existing_variable_with_namespace(self):
        parse_tree = self.parser('traffic:traffic_light == "green"')
        expected_node = Equal(self.traffic_objects['traffic_light'],
                              String("green"))
        eq_(parse_tree.root_node, expected_node)

    def test_non_existing_variable_without_namespace(self):
        assert_raises(ScopeError, self.parser, "~ non_existing_var")

    def test_non_existing_variable_with_namespace(self):
        assert_raises(ScopeError, self.parser, "~ traffic:non_existing_var")

    def test_variable_in_non_existing_namespace(self):
        assert_raises(ScopeError, self.parser, "~ bar:foo")

    def test_function_instead_of_variable(self):
        # "foo" is a function, so it cannot be used as a variable (without
        # parenthesis):
        try:
            self.parser('~ foo')
        except BadExpressionError as exc:
            eq_('"foo" represents a function, not a variable',
                six.text_type(exc))
        else:
            assert 0, '"foo" is a function, not a variable!'

    def test_named_constant(self):
        """Named constants must be supported."""
        parse_tree = self.parser('message == "Hello earth"')
        expected_node = Equal(String("Hello world"), String("Hello earth"))
        eq_(parse_tree.root_node, expected_node)

    # Tests for the parse action that makes the functions

    def test_existing_function_without_namespace(self):
        parse_tree = self.parser('~ foo("baz")')
        eq_(parse_tree.root_node, Not(PermissiveFunction(String("baz"))))

    def test_existing_function_with_namespace(self):
        parse_tree = self.parser('~ traffic:traffic_violation("pedestrians")')
        expected_node = Not(TrafficViolationFunc(String("pedestrians")))
        eq_(parse_tree.root_node, expected_node)

    def test_non_existing_function_without_namespace(self):
        assert_raises(ScopeError, self.parser, "~ non_existing_function()")

    def test_non_existing_function_with_namespace(self):
        assert_raises(ScopeError, self.parser, "~ traffic:non_existing_func()")

    def test_function_in_non_existing_namespace(self):
        assert_raises(ScopeError, self.parser, "~ bar:foo(123)")

    def test_variable_instead_of_function(self):
        # "bool" is a variable, so it cannot be used as a function (with
        # parenthesis):
        try:
            self.parser('~ bool()')
        except BadExpressionError as exc:
            eq_('"bool" is not a function', six.text_type(exc))
        else:
            assert 0, '"bool" is a variable, not a function!'