Пример #1
0
    def test_retrieving_namespace_with_partially_untrastlated_contents(self):
        """
        When a namespace is requested in a locale in which not all items are
        available, the namespace with global names should be returned instead.
        
        """
        bool_var = BoolVar()
        traffic = TrafficLightVar()
        st = SymbolTable(
            "global",
            (Bind("bool", BoolVar(), es="booleano", fr=u"booléen"),
             Bind("traffic", TrafficLightVar(), es=u"tráfico")),
            SymbolTable(
                "foo",
                (
                    Bind("bar", bool_var, es="fulano"),
                    Bind("baz", traffic, es="mengano", fr="bonjour"),
                ),
            ),
        )

        # Checking the namespace:
        namespace = st.get_namespace("fr")
        eq_(len(namespace.subnamespaces), 1)
        subnamespace = namespace.subnamespaces["foo"]
        subnamespace_objects = {
            'bar': bool_var,
            'bonjour': traffic,
        }
        eq_(subnamespace.objects, subnamespace_objects)
        expected_unbound_objects_global = {
            u'booléen': BoolVar(),
            'traffic': TrafficLightVar(),
        }
        eq_(namespace.objects, expected_unbound_objects_global)
Пример #2
0
    def test_equivalence(self):
        """
        Two function calls are equivalent not only if they share the same class,
        but also if their arguments are equivalent.
        
        """
        class FooFunction(Function):
            required_arguments = ("abc", )
            optional_arguments = {"xyz": LeafNode("123")}

        class CommutativeFunction(Function):
            required_arguments = range(2)
            argument_types = BooleanType
            is_commutative = True

        func1 = FooFunction(LeafNode("whatever"))
        func2 = FooFunction(LeafNode("whatever"))
        func3 = PermissiveFunction(BranchNode("baz"))
        func4 = PermissiveFunction(LeafNode("foo"))
        func5 = FooFunction(LeafNode("something"))
        func6 = CommutativeFunction(BoolVar(), TrafficLightVar())
        func7 = CommutativeFunction(TrafficLightVar(), BoolVar())

        assert_node_equivalence(
            (func1, func2),
            (func3, ),
            (func4, ),
            (func5, ),
            (func6, func7),
        )
Пример #3
0
 def test_retrieving_existing_global_object(self):
     objects = {
         'bool': BoolVar(),
         'traffic': TrafficLightVar(),
     }
     st = Namespace(objects)
     requested_object = st.get_object("bool")
     eq_(requested_object, BoolVar())
Пример #4
0
    def test_valid_argument_type(self):
        """Only arguments that implement the expected datatype are accepted."""
        class StronglyTypedFunction(Function):
            required_arguments = ("arg1", "arg2")
            argument_types = {'arg1': BooleanType, 'arg2': NumberType}

        StronglyTypedFunction(BoolVar(), NumVar())
        # Now arguments with the wrong types:
        assert_raises(BadCallError, StronglyTypedFunction, BoolVar(),
                      BoolVar())
        assert_raises(BadCallError, StronglyTypedFunction, NumVar(), NumVar())
        assert_raises(BadCallError, StronglyTypedFunction, NumVar(), BoolVar())
Пример #5
0
    def test_no_expected_datatype(self):
        """
        All the arguments are accepted if there's no expected type for them.
        
        """
        class WeaklyTypedFunction(Function):
            required_arguments = ("arg1", "arg2")

        WeaklyTypedFunction(BoolVar(), NumVar())
        WeaklyTypedFunction(BoolVar(), BoolVar())
        WeaklyTypedFunction(NumVar(), NumVar())
        WeaklyTypedFunction(NumVar(), BoolVar())
Пример #6
0
 def test_retrieving_existing_2nd_level_object(self):
     sub_objects = {
         'bool': BoolVar(),
         'traffic': TrafficLightVar(),
     }
     global_objects = {
         'foo': TrafficLightVar(),
     }
     sub_namespace = {'sub1': Namespace(sub_objects)}
     st = Namespace(global_objects, sub_namespace)
     requested_object = st.get_object("bool", ["sub1"])
     eq_(requested_object, BoolVar())
Пример #7
0
 def test_evaluation_order(self):
     """
     For efficiency, the second operand must not be evaluated if the first
     one returns False.
     
     """
     op1 = BoolVar()
     op2 = BoolVar()
     context = {'bool': False}
     And(op1, op2)(context)
     ok_(op1.evaluated)
     assert_false(op2.evaluated)
Пример #8
0
    def test_equivalence(self):
        """Two conjunctions are equivalent if they have the same operands."""
        op1 = And(BoolVar(), TrafficLightVar())
        op2 = And(TrafficLightVar(), BoolVar())
        op3 = And(DriversAwaitingGreenLightVar(), BoolVar())
        op4 = And(DriversAwaitingGreenLightVar(), BoolVar())
        op5 = Or(DriversAwaitingGreenLightVar(), BoolVar())

        assert_node_equivalence(
            (op1, op2),
            (op3, op4),
            (op5, ),
        )
Пример #9
0
    def test_homogeneouos_argument_types(self):
        """
        The argument types can be set just once if it's the same for all the
        arguments.
        
        """
        class StronglyTypedFunction(Function):
            required_arguments = ("arg1", "arg2")
            argument_types = BooleanType

        StronglyTypedFunction(BoolVar(), BoolVar())
        # Now arguments with the wrong types:
        assert_raises(BadCallError, StronglyTypedFunction, NumVar(), BoolVar())
        assert_raises(BadCallError, StronglyTypedFunction, BoolVar(), NumVar())
        assert_raises(BadCallError, StronglyTypedFunction, NumVar(), NumVar())
Пример #10
0
    def test_equivalence(self):
        """
        Two exclusive disjunctions are equivalent if they have the same
        operands.
        
        """
        op1 = Xor(BoolVar(), PedestriansCrossingRoad())
        op2 = Xor(PedestriansCrossingRoad(), BoolVar())
        op3 = Xor(DriversAwaitingGreenLightVar(), BoolVar())
        op4 = Xor(DriversAwaitingGreenLightVar(), BoolVar())
        op5 = Or(DriversAwaitingGreenLightVar(), BoolVar())

        assert_node_equivalence(
            (op1, op2),
            (op3, op4),
            (op5, ),
        )
Пример #11
0
 def test_retrieving_existing_3rd_level_object(self):
     third_level_objects = {
         'bool': BoolVar(),
     }
     second_level_objects = {
         'traffic': TrafficLightVar(),
     }
     global_objects = {
         'foo': TrafficLightVar(),
         'traffic-violation': TrafficViolationFunc(String("pedestrians")),
     }
     third_level_namespaces = {'sub2': Namespace(third_level_objects)}
     second_level_namespaces = {
         'sub1': Namespace(second_level_objects, third_level_namespaces)
     }
     st = Namespace(global_objects, second_level_namespaces)
     requested_object = st.get_object("bool", ["sub1", "sub2"])
     eq_(requested_object, BoolVar())
Пример #12
0
 def test_checking_object_and_subtable_sharing_localized_name(self):
     """
     It's valid for an object and a sub-table to share the localized name.
     
     """
     st1 = SymbolTable(
         "global",
         (Bind("current_day", BoolVar(), es="hoy"), ),
         SymbolTable("today", (), es="hoy"),
     )
     st2 = SymbolTable(
         "global",
         (Bind("current_day", BoolVar(), es="hoy"), ),
         # This sub-name will be called "hoy" in Spanish too:
         SymbolTable("hoy", ()),
     )
     eq_(st1.validate_scope(), None)
     eq_(st2.validate_scope(), None)
Пример #13
0
 def test_checking_object_and_subtable_sharing_global_name(self):
     """
     It's valid for an object and a sub-table to share the global name.
     
     """
     st = SymbolTable(
         "global",
         (Bind("today", BoolVar()), ),
         SymbolTable("today", ()),
     )
     eq_(st.validate_scope(), None)
Пример #14
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)
Пример #15
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, exc:
            eq_('"foo" represents a function, not a variable', unicode(exc))
        else:
Пример #16
0
    def test_name_clash_in_grand_children(self):
        """
        The scope must be validated even inside the sub-tables.
        
        """
        sciences_st1 = SymbolTable(
            "sciences",
            (),
            SymbolTable("maths", (), es=u"matemática"),
            SymbolTable("computing", ()),
            SymbolTable("maths", ()),
        )
        sciences_st2 = SymbolTable(
            "sciences",
            (),
            SymbolTable("maths", (), es=u"matemática"),
            SymbolTable("computing", ()),
            SymbolTable("mathematics", (), es=u"matemática"),
        )
        sciences_st3 = SymbolTable(
            "sciences",
            (),
            SymbolTable("maths", (), es=u"matemática"),
            SymbolTable("computing", ()),
            # This sub-table will be called "matemática" in Spanish too:
            SymbolTable(u"matemática", ()),
        )
        # Now a name clash at the objects level:
        sciences_st4 = SymbolTable("global", (
            Bind("foo", BoolVar()),
            Bind("foo", TrafficLightVar(), es="bar"),
        ))

        st1 = SymbolTable("global", (), sciences_st1,
                          SymbolTable("society", ()))
        st2 = SymbolTable("global", (), sciences_st2,
                          SymbolTable("society", ()))
        st3 = SymbolTable("global", (), sciences_st3,
                          SymbolTable("society", ()))
        st4 = SymbolTable("global", (), sciences_st4)

        assert_raises(ScopeError, st1.validate_scope)
        assert_raises(ScopeError, st2.validate_scope)
        assert_raises(ScopeError, st3.validate_scope)
        assert_raises(ScopeError, st4.validate_scope)
Пример #17
0
 def test_checking_valid_table(self):
     st = SymbolTable(
         "global",
         # Bindings/global objects:
         (
             Bind("bool", BoolVar(), es="booleano"),
             Bind("traffic", TrafficLightVar(), es=u"tráfico"),
         ),
         # Sub-tables:
         SymbolTable(
             "maths",
             (
                 Bind("pi", Number(3.1416)),
                 Bind("e", Number(2.7183)),
             ),
         ),
     )
     eq_(st.validate_scope(), None)
Пример #18
0
 def test_equivalence(self):
     tree1 = ConvertibleParseTree(PlaceholderVariable("my_variable"))
     tree2 = ConvertibleParseTree(PlaceholderVariable("my_variable"))
     tree3 = ConvertibleParseTree(String("hello"))
     tree4 = EvaluableParseTree(BoolVar())
     
     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)
Пример #19
0
    def test_retrieving_namespace_without_children(self):
        """
        A namespace shouldn't have sub-namespaces if the original symbol table
        doesn't have sub-tables.
        
        """
        bool_var = BoolVar()
        traffic = TrafficLightVar()
        st = SymbolTable(
            "global",
            (Bind("bool", bool_var,
                  es="booleano"), Bind("traffic", traffic, es=u"tráfico")),
        )

        # Checking the namespace:
        global_namespace = st.get_namespace()
        eq_(len(global_namespace.subnamespaces), 0)

        # Checking the namespace in Castilian:
        castilian_namespace = st.get_namespace("es")
        eq_(len(castilian_namespace.subnamespaces), 0)
Пример #20
0
    def test_retrieving_namespace_with_children(self):
        """
        A namespace should have sub-namespaces for the sub-tables of the
        original symbol table.
        
        """
        bool_var = BoolVar()
        traffic = TrafficLightVar()
        st = SymbolTable(
            "global",
            (Bind("bool", bool_var,
                  es="booleano"), Bind("traffic", traffic, es=u"tráfico")),
            SymbolTable(
                "foo",
                (
                    Bind("bar", bool_var, es="fulano"),
                    Bind("baz", traffic, es="mengano"),
                ),
            ),
        )

        # Checking the namespace:
        global_namespace = st.get_namespace()
        eq_(len(global_namespace.subnamespaces), 1)
        global_subnamespace = global_namespace.subnamespaces["foo"]
        global_subnamespace_objects = {
            'bar': bool_var,
            'baz': traffic,
        }
        eq_(global_subnamespace.objects, global_subnamespace_objects)

        # Checking the namespace in Castilian:
        castilian_namespace = st.get_namespace("es")
        eq_(len(castilian_namespace.subnamespaces), 1)
        castilian_subnamespace = castilian_namespace.subnamespaces["foo"]
        castilian_subnamespace_objects = {
            'fulano': bool_var,
            'mengano': traffic,
        }
        eq_(castilian_subnamespace.objects, castilian_subnamespace_objects)
Пример #21
0
 def test_string(self):
     tree = EvaluableParseTree(BoolVar())
     as_unicode = unicode(tree)
     expected = "Evaluable parse tree (Anonymous variable [BoolVar])"
     eq_(as_unicode, expected)
Пример #22
0
 def test_with_mixed_results(self):
     operation = And(BoolVar(), TrafficLightVar())
     assert_false(operation(dict(bool=False, traffic_light="red")))
Пример #23
0
 def test_with_both_results_as_false(self):
     operation = And(BoolVar(), TrafficLightVar())
     assert_false(operation(dict(bool=False, traffic_light="")))
Пример #24
0
 def test_with_both_results_as_true(self):
     operation = And(BoolVar(), TrafficLightVar())
     ok_(operation(dict(bool=True, traffic_light="red")))
Пример #25
0
 def test_with_mixed_results(self):
     operation = Xor(BoolVar(), TrafficLightVar())
     ok_(operation(dict(bool=False, traffic_light="red")))
Пример #26
0
 def test_with_both_results_as_true(self):
     operation = Xor(BoolVar(), TrafficLightVar())
     assert_false(operation(dict(bool=True, traffic_light="red")))
Пример #27
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 '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 '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)
Пример #28
0
 def test_representation(self):
     tree = ConvertibleParseTree(BoolVar())
     expected = "<Parse tree (convertible) " \
                "<Anonymous variable [BoolVar]>>"
     eq_(repr(tree), expected)
Пример #29
0
 class StronglyTypedFunction2(Function):
     required_arguments = ("arg1", )
     optional_arguments = {'arg2': BoolVar()}
     argument_types = {'arg1': BooleanType, 'arg2': BooleanType}
Пример #30
0
 def test_representation(self):
     tree = EvaluableParseTree(BoolVar())
     expected = "<Parse tree (evaluable) <Anonymous variable [BoolVar]>>"
     eq_(repr(tree), expected)