Example #1
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),
        )
Example #2
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)
Example #3
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())
Example #4
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, ),
        )
Example #5
0
 def test_retrieving_object_in_non_existing_subtable(self):
     global_objects = {
         'foo': TrafficLightVar(),
         'traffic-violation': TrafficViolationFunc(String("pedestrians")),
     }
     st = Namespace(global_objects, )
     assert_raises(ScopeError, st.get_object, "foo", ["doesn't", "exist"])
Example #6
0
 def test_retrieving_non_existing_object(self):
     global_objects = {
         'foo': TrafficLightVar(),
         'traffic-violation': TrafficViolationFunc(String("pedestrians")),
     }
     st = Namespace(global_objects, )
     assert_raises(ScopeError, st.get_object, "bool")
Example #7
0
 def test_constructor_with_objects(self):
     objects = [
         Bind("greeting", String("hey")),
         Bind("traffic", TrafficLightVar())
     ]
     st = SymbolTable("global", objects)
     eq_(st.objects, set(objects))
Example #8
0
 def test_evaluation(self):
     # Setup:
     traffic_light = TrafficLightVar()
     operation = Not(traffic_light)
     # Evaluation:
     ok_(operation.get_as_boolean(dict(traffic_light="")))
     assert_false(operation.get_as_boolean(dict(traffic_light="green")))
Example #9
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())
Example #10
0
 def test_duplicate_objects(self):
     """There must be no duplicate object."""
     # In the constructor:
     objects1 = [
         Bind("salutation", String("hey")),
         Bind("traffic", TrafficLightVar()),
         Bind("salutation", String("hey"))
     ]
     assert_raises(ScopeError, SymbolTable, "global", objects1)
     # Post-instantiation:
     objects2 = [
         Bind("salutation", String("hey")),
         Bind("traffic", TrafficLightVar())
     ]
     st = SymbolTable("global", objects2)
     assert_raises(ScopeError, st.add_object,
                   Bind("salutation", String("hey")))
Example #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())
Example #12
0
 def test_operand(self):
     """Operands alone can valid evaluable parse trees."""
     operand = TrafficLightVar()
     tree = EvaluableParseTree(operand)
     # True
     context = {'traffic_light': "red"}
     ok_(tree(context))
     # False
     context = {'traffic_light': None}
     assert_false(tree(context))
Example #13
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:
Example #14
0
 def test_unreusable_bindings(self):
     """
     Operand bindings and symbol tables can only be bound to a single parent
     symbol table.
     
     """
     # An operand binding:
     bind = Bind("traffic-light", TrafficLightVar())
     SymbolTable("traffic", [bind])
     assert_raises(ScopeError, SymbolTable, "baz", [bind])
     # A symbol table:
     st0 = SymbolTable("foo", [])
     SymbolTable("global", [], st0)
     assert_raises(ScopeError, SymbolTable, "bar", [], st0)
Example #15
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)
Example #16
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)
Example #17
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)
Example #18
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)
Example #19
0
 def test_with_mixed_results(self):
     operation = And(BoolVar(), TrafficLightVar())
     assert_false(operation(dict(bool=False, traffic_light="red")))
Example #20
0
 def test_with_both_results_as_false(self):
     operation = And(BoolVar(), TrafficLightVar())
     assert_false(operation(dict(bool=False, traffic_light="")))
Example #21
0
 def test_with_both_results_as_true(self):
     operation = And(BoolVar(), TrafficLightVar())
     ok_(operation(dict(bool=True, traffic_light="red")))
Example #22
0
    def test_equality(self):
        """Two bindings are equivalent if they have the same names."""
        op1 = TrafficLightVar()
        op2 = String("hey, where's my car?")
        bind1 = Bind("name1", op1)
        bind2 = Bind("name2", op2)
        bind3 = Bind("name2", op1)
        bind4 = Bind("name1", op2)
        bind5 = Bind("name1", op1)
        bind6 = Bind("name2", op2)
        bind7 = Bind("name1", op1, es="nombre1")
        bind8 = Bind("name1", op1, es_VE="nombre1", es="nombre1")
        bind9 = Bind("name1", op1, es="nombre1")

        ok_(bind1 == bind4)
        ok_(bind1 == bind5)
        ok_(bind2 == bind3)
        ok_(bind2 == bind6)
        ok_(bind3 == bind2)
        ok_(bind3 == bind6)
        ok_(bind4 == bind1)
        ok_(bind4 == bind5)
        ok_(bind5 == bind5)
        ok_(bind5 == bind1)
        ok_(bind5 == bind4)
        ok_(bind6 == bind2)
        ok_(bind6 == bind3)
        ok_(bind7 == bind9)
        ok_(bind9 == bind7)

        ok_(bind1 != None)
        ok_(bind1 != SymbolTable("name1", []))

        ok_(bind1 != bind2)
        ok_(bind1 != bind3)
        ok_(bind1 != bind6)
        ok_(bind1 != bind7)
        ok_(bind1 != bind8)
        ok_(bind1 != bind9)
        ok_(bind2 != bind1)
        ok_(bind2 != bind4)
        ok_(bind2 != bind5)
        ok_(bind2 != bind7)
        ok_(bind2 != bind8)
        ok_(bind2 != bind9)
        ok_(bind3 != bind1)
        ok_(bind3 != bind4)
        ok_(bind3 != bind5)
        ok_(bind3 != bind7)
        ok_(bind3 != bind8)
        ok_(bind3 != bind9)
        ok_(bind4 != bind2)
        ok_(bind4 != bind3)
        ok_(bind4 != bind6)
        ok_(bind4 != bind7)
        ok_(bind4 != bind8)
        ok_(bind4 != bind9)
        ok_(bind5 != bind2)
        ok_(bind5 != bind3)
        ok_(bind5 != bind6)
        ok_(bind5 != bind7)
        ok_(bind5 != bind8)
        ok_(bind5 != bind9)
        ok_(bind6 != bind1)
        ok_(bind6 != bind4)
        ok_(bind6 != bind5)
        ok_(bind6 != bind7)
        ok_(bind6 != bind8)
        ok_(bind6 != bind9)
        ok_(bind7 != bind1)
        ok_(bind7 != bind2)
        ok_(bind7 != bind3)
        ok_(bind7 != bind4)
        ok_(bind7 != bind5)
        ok_(bind7 != bind6)
        ok_(bind7 != bind8)
        ok_(bind8 != bind1)
        ok_(bind8 != bind2)
        ok_(bind8 != bind3)
        ok_(bind8 != bind4)
        ok_(bind8 != bind5)
        ok_(bind8 != bind6)
        ok_(bind8 != bind7)
        ok_(bind8 != bind9)
        ok_(bind9 != bind1)
        ok_(bind9 != bind2)
        ok_(bind9 != bind3)
        ok_(bind9 != bind4)
        ok_(bind9 != bind5)
        ok_(bind9 != bind6)
        ok_(bind9 != bind8)
Example #23
0
 def test_with_mixed_results(self):
     operation = Xor(BoolVar(), TrafficLightVar())
     ok_(operation(dict(bool=False, traffic_light="red")))
Example #24
0
 def test_with_both_results_as_true(self):
     operation = Xor(BoolVar(), TrafficLightVar())
     assert_false(operation(dict(bool=True, traffic_light="red")))
Example #25
0
 def test_hash_nullary(self):
     """The hash of a nullary function is the hash of the function class."""
     func = TrafficLightVar()
     eq_(hash(func), hash(TrafficLightVar))
Example #26
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)
Example #27
0
 def test_instance(self):
     """Class instances can be bound."""
     instance = TrafficLightVar()
     bound_instance = Bind("da_variable", instance)
     eq_(bound_instance.operand, instance)