def test_left_less_than_right(self): l_op = Number(1) r_op = NumVar() operation = LessEqual(l_op, r_op) context = {'num': 2} ok_(operation(context))
def test_left_greater_than_right(self): l_op = Number(3) r_op = NumVar() operation = LessEqual(l_op, r_op) context = {'num': 2} assert_false(operation(context))
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_localized_grammars(self): castilian_grammar = Grammar(decimal_separator=",", thousands_separator=".") mgr = ConvertibleParseManager(Grammar(), es=castilian_grammar) parse_tree = mgr.parse(u"tráfico:peatones_cruzando_calle <= 3,00", "es") expected_tree = ConvertibleParseTree( LessEqual( PlaceholderVariable("peatones_cruzando_calle", (u"tráfico", )), Number(3.0))) 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_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_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_identical_values(self): l_op = Number(3) r_op = Number(3) operation = LessEqual(l_op, r_op) ok_(operation(None))
def convert_less_equal(self, master_operand, slave_operand): return LessEqual(master_operand, slave_operand)
class TestDefaultGrammar(BaseGrammarTest): """ Tests for the parser of the default/generic grammar. """ grammar = Grammar() expressions = { # Literals-only expressions: ' "a string" == 245 ': Equal(String("a string"), Number(245)), ' 2 > 5 ': GreaterThan(Number(2), Number(5)), # Identifiers-only expressions: ' today > yesterday ': GreaterThan(PlaceholderVariable("today"), PlaceholderVariable("yesterday")), 'time:today > time:yesterday ': GreaterThan(PlaceholderVariable("today", ("time", )), PlaceholderVariable("yesterday", ("time", ))), # Literals + non-literal expressions: 'today > "1999-06-01"': GreaterThan(PlaceholderVariable("today"), String("1999-06-01")), 'get_parents("Gustavo") == {"Liliana", "Carlos"}': Equal(PlaceholderFunction("get_parents", None, String("Gustavo")), Set(String("Liliana"), String("Carlos"))), # Set-specific operations: u'"hi" ∈ {"hi", "bye"}': BelongsTo(String("hi"), Set(String("hi"), String("bye"))), u'salutation ∈ {"hi", "bye"}': BelongsTo(PlaceholderVariable("salutation"), Set(String("hi"), String("bye"))), u'"good morning" ∈ salutations': BelongsTo(String("good morning"), PlaceholderVariable("salutations")), u'relatives:sister ∈ relatives:siblings': BelongsTo(PlaceholderVariable("sister", ("relatives", )), PlaceholderVariable("siblings", ("relatives", ))), u'{"hi", "bye"} ⊂ {"hello", "hi", "bye"}': IsSubset(Set(String("hi"), String("bye")), Set(String("hello"), String("hi"), String("bye"))), u'salutations ⊂ {"morning", "hi", "bye", "later"}': IsSubset( PlaceholderVariable("salutations"), Set(String("morning"), String("hi"), String("bye"), String("later"))), u'{"hi", "bye"} ⊂ salutations': IsSubset(Set(String("hi"), String("bye")), PlaceholderVariable("salutations")), u'relatives:siblings ⊂ relatives:everyone': IsSubset(PlaceholderVariable("siblings", ("relatives", )), PlaceholderVariable("everyone", ("relatives", ))), # Relational operations: 'now == today:time': Equal(PlaceholderVariable("now"), PlaceholderVariable("time", ("today", ))), '3.1416 == Pi': Equal(Number(3.1416), PlaceholderVariable("pi")), 'Pi == 3.1416': Equal(PlaceholderVariable("pi"), Number(3.1416)), 'days:today != days:yesterday': NotEqual(PlaceholderVariable("today", ("days", )), PlaceholderVariable("yesterday", ("days", ))), '3.00 != Pi': NotEqual(Number(3.0), PlaceholderVariable("pi")), 'Pi != 3.00': Equal(PlaceholderVariable("pi"), Number(3.00)), 'days:today > days:yesterday': GreaterThan(PlaceholderVariable("today", ("days", )), PlaceholderVariable("yesterday", ("days", ))), '3.00 > Pi': GreaterThan(Number(3.0), PlaceholderVariable("pi")), 'Pi > 3.00': GreaterThan(PlaceholderVariable("pi"), Number(3.00)), 'days:today < days:yesterday': LessThan(PlaceholderVariable("today", ("days", )), PlaceholderVariable("yesterday", ("days", ))), '3.00 < Pi': LessThan(Number(3.0), PlaceholderVariable("pi")), 'Pi < 3.00': LessThan(PlaceholderVariable("pi"), Number(3.00)), 'days:today >= days:yesterday': GreaterEqual(PlaceholderVariable("today", ("days", )), PlaceholderVariable("yesterday", ("days", ))), '3.00 >= Pi': GreaterEqual(Number(3.0), PlaceholderVariable("pi")), 'Pi >= 3.00': GreaterEqual(PlaceholderVariable("pi"), Number(3.00)), 'days:today <= days:yesterday': LessEqual(PlaceholderVariable("today", ("days", )), PlaceholderVariable("yesterday", ("days", ))), '3.00 <= Pi': LessEqual(Number(3.0), PlaceholderVariable("pi")), 'Pi <= 3.00': LessEqual(PlaceholderVariable("pi"), Number(3.00)), # Logical connectives: '~today_will_rain()': Not(PlaceholderFunction("today_will_rain")), '~(today_will_rain())': Not(PlaceholderFunction("today_will_rain")), '~ today_will_rain()': Not(PlaceholderFunction("today_will_rain")), '~~today_will_rain()': Not(Not(PlaceholderFunction("today_will_rain"))), '~ today_is_friday': Not(PlaceholderVariable("today_is_friday")), '~ time:days:today > "1999-06-01"': Not( GreaterThan(PlaceholderVariable("today", ("time", "days")), String("1999-06-01"))), '~ (time:days:today > "1999-06-01")': Not( GreaterThan(PlaceholderVariable("today", ("time", "days")), String("1999-06-01"))), '~ today_is_friday & today_will_rain': And(Not(PlaceholderVariable("today_is_friday")), PlaceholderVariable("today_will_rain")), '~ today_is_friday & ~ today_will_rain': And(Not(PlaceholderVariable("today_is_friday")), Not(PlaceholderVariable("today_will_rain"))), 'today_is_friday & ~ today_will_rain': And(PlaceholderVariable("today_is_friday"), Not(PlaceholderVariable("today_will_rain"))), '~ (today_is_friday & today_will_rain)': Not( And(PlaceholderVariable("today_is_friday"), PlaceholderVariable("today_will_rain"))), '~ X > 3 & Z < X': And(Not(GreaterThan(PlaceholderVariable("X"), Number(3))), LessThan(PlaceholderVariable("Z"), PlaceholderVariable("X"))), '~ X > 3 & ~ Z < X': And(Not(GreaterThan(PlaceholderVariable("X"), Number(3))), Not(LessThan(PlaceholderVariable("Z"), PlaceholderVariable("X")))), 'X > 3 & ~ Z < X': And(GreaterThan(PlaceholderVariable("X"), Number(3)), Not(LessThan(PlaceholderVariable("Z"), PlaceholderVariable("X")))), '~ (X > 3 & Z < X)': Not( And(GreaterThan(PlaceholderVariable("X"), Number(3)), LessThan(PlaceholderVariable("Z"), PlaceholderVariable("X")))), '~ (X > 3 ^ Z < X)': Not( Xor(GreaterThan(PlaceholderVariable("X"), Number(3)), LessThan(PlaceholderVariable("Z"), PlaceholderVariable("X")))), '~ (X > 3 | Z < X)': Not( Or(GreaterThan(PlaceholderVariable("X"), Number(3)), LessThan(PlaceholderVariable("Z"), PlaceholderVariable("X")))), 'today_will_rain() & Pi > 3.0': And(PlaceholderFunction("today_will_rain"), GreaterThan(PlaceholderVariable("Pi"), Number(3.0))), 'weather:today_rains & Pi > e & today_is_monday()': And( PlaceholderVariable("today_rains", ("weather", )), And( GreaterThan(PlaceholderVariable("Pi"), PlaceholderVariable("e")), PlaceholderFunction("today_is_monday"))), 'weather:today_rains & (Pi > e & today_is_monday())': And( PlaceholderVariable("today_rains", ("weather", )), And( GreaterThan(PlaceholderVariable("Pi"), PlaceholderVariable("e")), PlaceholderFunction("today_is_monday"))), '(weather:today_rains & Pi > e) & today_is_monday()': And( And( PlaceholderVariable("today_rains", ("weather", )), GreaterThan(PlaceholderVariable("Pi"), PlaceholderVariable("e"))), PlaceholderFunction("today_is_monday")), 'today_will_rain() ^ Pi > 3.0': Xor(PlaceholderFunction("today_will_rain"), GreaterThan(PlaceholderVariable("Pi"), Number(3.0))), 'weather:today_rains ^ Pi > e ^ today_is_monday()': Xor( PlaceholderVariable("today_rains", ("weather", )), Xor( GreaterThan(PlaceholderVariable("Pi"), PlaceholderVariable("e")), PlaceholderFunction("today_is_monday"))), 'weather:today_rains ^ (Pi > e ^ today_is_monday())': Xor( PlaceholderVariable("today_rains", ("weather", )), Xor( GreaterThan(PlaceholderVariable("Pi"), PlaceholderVariable("e")), PlaceholderFunction("today_is_monday"))), '(weather:today_rains ^ Pi > e) ^ today_is_monday()': Xor( Xor( PlaceholderVariable("today_rains", ("weather", )), GreaterThan(PlaceholderVariable("Pi"), PlaceholderVariable("e"))), PlaceholderFunction("today_is_monday")), 'today_will_rain() | Pi > 3.0': Or(PlaceholderFunction("today_will_rain"), GreaterThan(PlaceholderVariable("Pi"), Number(3.0))), 'weather:today_rains | Pi > e | today_is_monday()': Or( PlaceholderVariable("today_rains", ("weather", )), Or( GreaterThan(PlaceholderVariable("Pi"), PlaceholderVariable("e")), PlaceholderFunction("today_is_monday"))), 'weather:today_rains | (Pi > e | today_is_monday())': Or( PlaceholderVariable("today_rains", ("weather", )), Or( GreaterThan(PlaceholderVariable("Pi"), PlaceholderVariable("e")), PlaceholderFunction("today_is_monday"))), '(weather:today_rains | Pi > e) | today_is_monday()': Or( Or( PlaceholderVariable("today_rains", ("weather", )), GreaterThan(PlaceholderVariable("Pi"), PlaceholderVariable("e"))), PlaceholderFunction("today_is_monday")), # Checking operator precedence rules: 'today == "monday" & yesterday != "sunday" ^ Y > 0': Xor( And(Equal(PlaceholderVariable("today"), String("monday")), NotEqual(PlaceholderVariable("yesterday"), String("sunday"))), GreaterThan(PlaceholderVariable("Y"), Number(0))), '(today == "monday" & yesterday != "sunday") ^ Y > 0': Xor( And(Equal(PlaceholderVariable("today"), String("monday")), NotEqual(PlaceholderVariable("yesterday"), String("sunday"))), GreaterThan(PlaceholderVariable("Y"), Number(0))), 'today == "monday" & (yesterday != "sunday" ^ Y > 0)': And( Equal(PlaceholderVariable("today"), String("monday")), Xor(NotEqual(PlaceholderVariable("yesterday"), String("sunday")), GreaterThan(PlaceholderVariable("Y"), Number(0))), ), 'today == "monday" ^ yesterday != "sunday" & Y > 0': Xor( Equal(PlaceholderVariable("today"), String("monday")), And(NotEqual(PlaceholderVariable("yesterday"), String("sunday")), GreaterThan(PlaceholderVariable("Y"), Number(0))), ), 'today == "monday" ^ (yesterday != "sunday" & Y > 0)': Xor( Equal(PlaceholderVariable("today"), String("monday")), And(NotEqual(PlaceholderVariable("yesterday"), String("sunday")), GreaterThan(PlaceholderVariable("Y"), Number(0))), ), '(today == "monday" ^ yesterday != "sunday") & Y > 0': And( Xor(Equal(PlaceholderVariable("today"), String("monday")), NotEqual(PlaceholderVariable("yesterday"), String("sunday"))), GreaterThan(PlaceholderVariable("Y"), Number(0))), 'today == "monday" & yesterday != "sunday" | Y > 0': Or( And(Equal(PlaceholderVariable("today"), String("monday")), NotEqual(PlaceholderVariable("yesterday"), String("sunday"))), GreaterThan(PlaceholderVariable("Y"), Number(0))), '(today == "monday" & yesterday != "sunday") | Y > 0': Or( And(Equal(PlaceholderVariable("today"), String("monday")), NotEqual(PlaceholderVariable("yesterday"), String("sunday"))), GreaterThan(PlaceholderVariable("Y"), Number(0))), 'today == "monday" & (yesterday != "sunday" | Y > 0)': And( Equal(PlaceholderVariable("today"), String("monday")), Or(NotEqual(PlaceholderVariable("yesterday"), String("sunday")), GreaterThan(PlaceholderVariable("Y"), Number(0))), ), 'today == "monday" | yesterday != "sunday" & Y > 0': Or( Equal(PlaceholderVariable("today"), String("monday")), And(NotEqual(PlaceholderVariable("yesterday"), String("sunday")), GreaterThan(PlaceholderVariable("Y"), Number(0))), ), 'today == "monday" | (yesterday != "sunday" & Y > 0)': Or( Equal(PlaceholderVariable("today"), String("monday")), And(NotEqual(PlaceholderVariable("yesterday"), String("sunday")), GreaterThan(PlaceholderVariable("Y"), Number(0))), ), '(today == "monday" | yesterday != "sunday") & Y > 0': And( Or(Equal(PlaceholderVariable("today"), String("monday")), NotEqual(PlaceholderVariable("yesterday"), String("sunday"))), GreaterThan(PlaceholderVariable("Y"), Number(0))), 'today == "monday" ^ yesterday != "sunday" | Y > 0': Or( Xor(Equal(PlaceholderVariable("today"), String("monday")), NotEqual(PlaceholderVariable("yesterday"), String("sunday"))), GreaterThan(PlaceholderVariable("Y"), Number(0))), '(today == "monday" ^ yesterday != "sunday") | Y > 0': Or( Xor(Equal(PlaceholderVariable("today"), String("monday")), NotEqual(PlaceholderVariable("yesterday"), String("sunday"))), GreaterThan(PlaceholderVariable("Y"), Number(0))), 'today == "monday" ^ (yesterday != "sunday" | Y > 0)': Xor( Equal(PlaceholderVariable("today"), String("monday")), Or(NotEqual(PlaceholderVariable("yesterday"), String("sunday")), GreaterThan(PlaceholderVariable("Y"), Number(0))), ), 'today == "monday" | yesterday != "sunday" ^ Y > 0': Or( Equal(PlaceholderVariable("today"), String("monday")), Xor(NotEqual(PlaceholderVariable("yesterday"), String("sunday")), GreaterThan(PlaceholderVariable("Y"), Number(0))), ), 'today == "monday" | (yesterday != "sunday" ^ Y > 0)': Or( Equal(PlaceholderVariable("today"), String("monday")), Xor(NotEqual(PlaceholderVariable("yesterday"), String("sunday")), GreaterThan(PlaceholderVariable("Y"), Number(0))), ), '(today == "monday" | yesterday != "sunday") ^ Y > 0': Xor( Or(Equal(PlaceholderVariable("today"), String("monday")), NotEqual(PlaceholderVariable("yesterday"), String("sunday"))), GreaterThan(PlaceholderVariable("Y"), Number(0))), 'W == 0 & X != 1 ^ Y > 2 | Z < 3': Or( Xor( And(Equal(PlaceholderVariable("W"), Number(0)), NotEqual(PlaceholderVariable("X"), Number(1))), GreaterThan(PlaceholderVariable("Y"), Number(2))), LessThan(PlaceholderVariable("Z"), Number(3))), 'W == 0 | X != 1 ^ Y > 2 & Z < 3': Or( Equal(PlaceholderVariable("W"), Number(0)), Xor( NotEqual(PlaceholderVariable("X"), Number(1)), And(GreaterThan(PlaceholderVariable("Y"), Number(2)), LessThan(PlaceholderVariable("Z"), Number(3))), ), ), 'W == 0 | (X != 1 ^ (Y > 2 & Z < 3))': Or( Equal(PlaceholderVariable("W"), Number(0)), Xor( NotEqual(PlaceholderVariable("X"), Number(1)), And(GreaterThan(PlaceholderVariable("Y"), Number(2)), LessThan(PlaceholderVariable("Z"), Number(3))), ), ), '(W == 0 | X != 1) ^ (Y > 2 & Z < 3)': Xor( Or(Equal(PlaceholderVariable("W"), Number(0)), NotEqual(PlaceholderVariable("X"), Number(1))), And(GreaterThan(PlaceholderVariable("Y"), Number(2)), LessThan(PlaceholderVariable("Z"), Number(3)))), '(W == 0 | X != 1 ^ Y > 2) & Z < 3': And( Or( Equal(PlaceholderVariable("W"), Number(0)), Xor( NotEqual(PlaceholderVariable("X"), Number(1)), GreaterThan(PlaceholderVariable("Y"), Number(2)), )), LessThan(PlaceholderVariable("Z"), Number(3))), '((W == 0 | X != 1) ^ Y > 2) & Z < 3': And( Xor( Or(Equal(PlaceholderVariable("W"), Number(0)), NotEqual(PlaceholderVariable("X"), Number(1))), GreaterThan(PlaceholderVariable("Y"), Number(2))), LessThan(PlaceholderVariable("Z"), Number(3))), '(W == 0 | (X != 1 ^ Y > 2)) & Z < 3': And( Or( Equal(PlaceholderVariable("W"), Number(0)), Xor(NotEqual(PlaceholderVariable("X"), Number(1)), GreaterThan(PlaceholderVariable("Y"), Number(2)))), LessThan(PlaceholderVariable("Z"), Number(3))), 'W == 0 | (X != 1 ^ Y > 2 & Z < 3)': Or( Equal(PlaceholderVariable("W"), Number(0)), Xor( NotEqual(PlaceholderVariable("X"), Number(1)), And(GreaterThan(PlaceholderVariable("Y"), Number(2)), LessThan(PlaceholderVariable("Z"), Number(3))))), 'W == 0 | (X != 1 ^ (Y > 2 & Z < 3))': Or( Equal(PlaceholderVariable("W"), Number(0)), Xor( NotEqual(PlaceholderVariable("X"), Number(1)), And(GreaterThan(PlaceholderVariable("Y"), Number(2)), LessThan(PlaceholderVariable("Z"), Number(3))))), 'W == 0 | ((X != 1 ^ Y > 2) & Z < 3)': Or( Equal(PlaceholderVariable("W"), Number(0)), And( Xor( NotEqual(PlaceholderVariable("X"), Number(1)), GreaterThan(PlaceholderVariable("Y"), Number(2)), ), LessThan(PlaceholderVariable("Z"), Number(3)))), # Let's make sure whitespace doesn't change anything: ''' variable == "hi" ''': Equal(PlaceholderVariable("variable"), String("hi")), ''' variable == "hi" ''': Equal(PlaceholderVariable("variable"), String("hi")), ''' \t variable == "hi" & \t today_is_thursday() ''': And(Equal(PlaceholderVariable("variable"), String("hi")), PlaceholderFunction("today_is_thursday")), } badformed_expressions = ( "", " ", "\t", "\n", "\r", "== 3 4", "3 4 ==", ) single_operands = { # ----- Strings '"oneword"': String("oneword"), '"double quotes"': String("double quotes"), "'single quotes'": String("single quotes"), "''": String(""), '""': String(""), "'something with \"quotes\"'": String('something with "quotes"'), '"something with \'quotes\'"': String("something with 'quotes'"), u'"áéíóúñçÁÉÍÓÚÑÇ"': String(u"áéíóúñçÁÉÍÓÚÑÇ"), u'"海納百川,有容乃大"': String(u"海納百川,有容乃大"), u"'مقالة مختارة'": String(u"مقالة مختارة"), u'"вільної енциклопедії"': String(u"вільної енциклопедії"), # ----- Numbers '1': Number(1), '01': Number(1), '5000': Number(5000), '+3': Number(3), '-3': Number(-3), '2.34': Number(2.34), '2.2': Number(2.2), '+3.1416': Number(3.1416), '-3.1416': Number(-3.1416), '5,000': Number(5000), '1,000,000.34': Number(1000000.34), '+1,000,000.22': Number(1000000.22), '-1,000,000.22': Number(-1000000.22), # ----- Sets: ' {} ': Set(), '{{}, {}}': Set(Set(), Set()), '{1,000, 3.05}': Set(Number(1000), Number(3.05)), '{1,234,567}': Set(Number(1234567)), '{23,24,25}': Set(Number(23), Number(24), Number(25)), '{100, 200, 300}': Set(Number(100), Number(200), Number(300)), '{1, 2, {"orange", "apple"}, 3}': Set( Number(1), Number(2), Number(3), Set(String("orange"), String("apple")) ), u'{"españa", {"caracas", {"las chimeneas", "el trigal"}}, "france"}': \ Set( String(u"españa"), String("france"), Set( String("caracas"), Set(String("el trigal"), String("las chimeneas")) ), ), '{var1, var2}': Set(PlaceholderVariable("var1"), PlaceholderVariable("var2")), '{var, "string"}': Set(PlaceholderVariable("var"), String("string")), '{3, var, "string"}': Set(Number(3), String("string"), PlaceholderVariable("var")), '{varA, funcB()}': Set(PlaceholderVariable("varA"), PlaceholderFunction("funcB")), '{"hi", 3.1416, len({1, 2, 3, 5, 7}), var0}': Set( String("hi"), Number(3.1416), PlaceholderFunction("len", (), Set( Number(1), Number(2), Number(3), Number(5), Number(7))), PlaceholderVariable("var0") ), # ----- Variables: 'today': PlaceholderVariable("today"), 'camelCase': PlaceholderVariable("camelCase"), 'with_underscore': PlaceholderVariable("with_underscore"), ' v1 ': PlaceholderVariable("v1"), 'var1_here': PlaceholderVariable("var1_here"), u'résumé': PlaceholderVariable(u"résumé"), u'有容乃大': PlaceholderVariable(u"有容乃大"), ' spaces': PlaceholderVariable("spaces"), 'spaces ': PlaceholderVariable("spaces"), ' spaces ': PlaceholderVariable("spaces"), '_protected_var': PlaceholderVariable("_protected_var"), '__private_var': PlaceholderVariable("__private_var"), 'one_underscore': PlaceholderVariable("one_underscore"), 'two__underscores__here': PlaceholderVariable("two__underscores__here"), 'case_insensitive_var': PlaceholderVariable("CASE_INSENSITIVE_VAR"), 'CASE_INSENSITIVE_VAR': PlaceholderVariable("case_insensitive_var"), 'cAsE_iNsEnSiTiVe_VaR': PlaceholderVariable("CaSe_InSeNsItIvE_vAr"), u'MAYÚSCULA_minúscula': PlaceholderVariable(u"mayúscula_MINÚSCULA"), 'ns:variable': PlaceholderVariable("variable", ("ns", )), 'ns0:ns1:variable': PlaceholderVariable("variable", ("ns0", "ns1")), 'ns0:ns1:ns2:variable': PlaceholderVariable("variable", ("ns0", "ns1", "ns2")), 'ns:sub_ns:variable': PlaceholderVariable("variable", ("ns", "sub_ns")), u'ñŝ0:ñŝ1:variable': PlaceholderVariable("variable", (u"ñŝ0", u"ñŝ1")), # ----- Functions: 'stop()': PlaceholderFunction("stop"), 'stop ()': PlaceholderFunction("stop"), 'stop( )': PlaceholderFunction("stop"), 'stop ( )': PlaceholderFunction("stop"), 'camelCase()': PlaceholderFunction("camelCase"), 'with_underscore()': PlaceholderFunction("with_underscore"), ' v1() ': PlaceholderFunction("v1"), 'var1_here()': PlaceholderFunction("var1_here"), u'résumé()': PlaceholderFunction(u"résumé"), u'有容乃大()': PlaceholderFunction(u"有容乃大"), ' spaces()': PlaceholderFunction("spaces"), 'spaces() ': PlaceholderFunction("spaces"), ' spaces() ': PlaceholderFunction("spaces"), '_protected_function()': PlaceholderFunction("_protected_function"), '__private_function()': PlaceholderFunction("__private_function"), 'one_underscore()': PlaceholderFunction("one_underscore"), 'two__underscores__()': PlaceholderFunction("two__underscores__"), 'case_insensitive_func()': PlaceholderFunction("CASE_INSENSITIVE_FUNC"), 'CASE_INSENSITIVE_FUNC()': PlaceholderFunction("case_insensitive_func"), 'cAsE_iNsEnSiTiVe_FuNc()': PlaceholderFunction("CaSe_InSeNsItIvE_fUnC"), u'MAYÚSCULA_minúscula()': PlaceholderFunction(u"mayúscula_MINÚSCULA"), 'func("argument")': PlaceholderFunction("func", (), String("argument")), 'function("arg1", variable, 3)': PlaceholderFunction("function", (), String("arg1"), PlaceholderVariable("variable"), Number(3), ), 'function("arg1", ns:variable, 3)': PlaceholderFunction( "function", (), String("arg1"), PlaceholderVariable("variable", ("ns", )), Number(3), ), 'ns:function("arg1", ns:variable, 3)': PlaceholderFunction( "function", ("ns", ), String("arg1"), PlaceholderVariable("variable", ("ns", )), Number(3), ), 'function("arg1", ns:sub_function(), 3.0)': PlaceholderFunction( "function", (), String("arg1"), PlaceholderFunction("sub_function", ("ns", )), Number(3), ), 'ns:function("arg1", ns:sub_function(), 3.0)': PlaceholderFunction( "function", ("ns", ), String("arg1"), PlaceholderFunction("sub_function", ("ns", )), Number(3), ), 'ns:function()': PlaceholderFunction("function", ("ns", )), 'ns0:ns1:function()': PlaceholderFunction("function", ("ns0", "ns1")), 'ns0:ns1:ns2:function()': PlaceholderFunction("function", ("ns0", "ns1", "ns2")), 'ns:sub_ns:function("with argument")': PlaceholderFunction("function", ("ns", "sub_ns"), String("with argument"), ), u'ñŝ:ñś1:function()': PlaceholderFunction("function", (u"ñŝ", u"ñś1")), u'ñŝ:ñś1:función()': PlaceholderFunction(u"función", (u"ñŝ", u"ñś1")), } invalid_operands = ( # Invalid strings: '\'mixed quotes"', # Invalid numbers: "3 . 1416", "3. 1416", "3 .1416", "1,00", "12.4,500,000", # Invalid variables: "dashes-here-cant-you-see-them", "1st_variable", "25th_variable", "namespace-here:variable", "1stnamespace:var", "global:2ndlevel:var", "namespace:1st_variable", # Invalid functions: "func(", "func)", "func)(", "func[]", "func{}", "func(,)", "func(arg1, )", "func(, arg2)", "func(, arg2, )", "function-name()", "1st_function()", "25th_function()", "namespace-here:function()", "1stnamespace:function()", "global:2ndlevel:function()", "namespace:1st_function()", "foo( bad-namespace:baz() )", # Invalid sets: "[]", "{]", "[}", "}{", "{key: 'value'}", "[element1, element2, element3]", "{element 1, element 2}", "{element1; element2; element3}", "{element == 'string'}", # Default operators: "==", "!=", "<", ">", "<=", ">=", "~", "&", "^", "|", u"∈", u"⊂", # Miscellaneous: "-", "this is definitely not an operand", ) def test_custom_tokens_against_trees(self): """ All the custom tokens in the grammar must be taken into account by the parser. To test that custom tokens are used, and in order to test many scenarios writen few lines of code, we're going to convert operation nodes into boolean expressions (using the relevant grammar), and then these expressions will be parsed to check if the result is the original tree. """ grammars = ( # A grammar that overrides all the default tokens: Grammar( **{ 'not': "not", 'and': "and", 'xor': "xor", 'or': "or", 'eq': "equals", 'ne': "different-from", 'lt': "less-than", 'le': "less-equal", 'gt': "greater-than", 'ge': "greater-equal", 'belongs_to': "belongs-to", 'is_subset': "is-subset-of", 'set_start': "\\", 'set_end': "/", 'element_separator': ";", 'arguments_start': "[", 'arguments_end': "]", 'arguments_separator': ";", 'namespace_separator': ".", }), # Now let's try a grammar where some operators represent the # initial characters of other operators: Grammar( **{ 'eq': "is", 'ne': "isn't", 'lt': "is less than", 'gt': "is greater than", 'le': "is less than or equal to", 'ge': "is greater than or equal to", 'belongs_to': "is included in", 'is_subset': "is subset of", })) for grammar_num in range(len(grammars)): grammar = grammars[grammar_num] parser = ConvertibleParser(grammar) convert_to_string = StringConverter(grammar) for operation in self.expressions.values(): expression = convert_to_string(operation) # Using a Nose test generator: def check(): new_operation = parser(expression).root_node eq_( operation, new_operation, u'Original operation: %s --- Returned operation: %s' % (repr(operation), repr(new_operation))) check.description = (u"The following expression is valid in " u"the grammar #%s: %s" % (grammar_num, expression)) yield check