Changeset 8
- Timestamp:
- 12/08/04 12:22:49 (4 years ago)
- Files:
-
- trunk/airspeed.py (modified) (1 diff)
- trunk/airspeed_test.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/airspeed.py
r7 r8 166 166 167 167 168 class Parser: 169 def __init__(self): 170 self.data = {} 168 class Template: 169 def __init__(self, content): 170 self.content = content 171 self.evaluator = None 171 172 172 def merge(self, content):173 def merge(self, namespace): 173 174 output = [] 174 evaluator = BlockEvaluator() 175 for token_type, token_value in Tokeniser().tokenise(str(content)): 176 evaluator.feed(token_type, token_value) 175 if not self.evaluator: 176 self.evaluator = BlockEvaluator() 177 for token_type, token_value in Tokeniser().tokenise(self.content): 178 self.evaluator.feed(token_type, token_value) 177 179 output = StringIO.StringIO() 178 evaluator.evaluate(output, self.data)180 self.evaluator.evaluate(output, namespace) 179 181 return output.getvalue() 180 182 181 def __setitem__(self, name, value):182 self.data[name] = value183 184 185 class Template:186 187 def __init__(self, content):188 self.content = content189 190 def __str__(self):191 return self.content192 193 194 trunk/airspeed_test.py
r7 r8 5 5 6 6 7 class ParserTestCase(TestCase):7 class TemplateTestCase(TestCase): 8 8 9 9 def test_parser_returns_input_when_there_is_nothing_to_substitute(self): 10 parser = airspeed.Parser()11 10 template = airspeed.Template("<html></html>") 12 parsedContent = parser.merge(template) 13 self.assertEquals("<html></html>", parsedContent) 11 self.assertEquals("<html></html>", template.merge({})) 14 12 15 13 def test_parser_substitutes_string_added_to_the_context(self): 16 parser = airspeed.Parser()17 14 template = airspeed.Template("Hello $name") 18 parser["name"] = "Chris" 19 parsedContent = parser.merge(template) 20 self.assertEquals("Hello Chris", parsedContent) 15 self.assertEquals("Hello Chris", template.merge({"name": "Chris"})) 21 16 22 17 def test_unmatched_name_does_not_get_substituted(self): 23 parser = airspeed.Parser()24 18 template = airspeed.Template("Hello $name") 25 parsedContent = parser.merge(template) 26 self.assertEquals("Hello $name", parsedContent) 19 self.assertEquals("Hello $name", template.merge({})) 27 20 28 21 def test_silent_substitution_for_unmatched_values(self): 29 parser = airspeed.Parser()30 22 template = airspeed.Template("Hello $!name") 31 parsedContent = parser.merge(template) 32 self.assertEquals("Hello ", parsedContent) 33 parser["name"] = "world" 34 self.assertEquals("Hello world", parser.merge(template)) 23 self.assertEquals("Hello ", template.merge({})) 24 self.assertEquals("Hello world", template.merge({"name": "world"})) 35 25 36 26 def test_embed_substitution_value_in_braces_gets_handled(self): 37 parser = airspeed.Parser()38 27 template = airspeed.Template("Hello ${name}.") 39 parser["name"] = "World" 40 self.assertEquals("Hello World.", parser.merge(template)) 28 self.assertEquals("Hello World.", template.merge({"name": "World"})) 41 29 42 30 def test_unmatched_braces_raises_exception(self): 43 parser = airspeed.Parser()44 31 template = airspeed.Template("Hello ${name.") 45 parser["name"] = "World" 46 self.assertRaises(airspeed.TemplateSyntaxError, parser.merge, template) 32 self.assertRaises(airspeed.TemplateSyntaxError, template.merge, {}) 47 33 48 34 def test_unmatched_trailing_brace_preserved(self): 49 parser = airspeed.Parser()50 35 template = airspeed.Template("Hello $name}.") 51 parser["name"] = "World" 52 self.assertEquals("Hello World}.", parser.merge(template)) 36 self.assertEquals("Hello World}.", template.merge({"name": "World"})) 53 37 54 38 def test_can_return_value_from_an_attribute_of_a_context_object(self): 55 parser = airspeed.Parser()56 39 template = airspeed.Template("Hello $name.first_name") 57 40 class MyObj: pass 58 41 o = MyObj() 59 42 o.first_name = 'Chris' 60 parser["name"] = o 61 self.assertEquals("Hello Chris", parser.merge(template)) 43 self.assertEquals("Hello Chris", template.merge({"name": o})) 62 44 63 45 def test_can_return_value_from_an_attribute_of_a_context_object(self): 64 parser = airspeed.Parser()65 46 template = airspeed.Template("Hello $name.first_name") 66 47 class MyObj: pass 67 48 o = MyObj() 68 49 o.first_name = 'Chris' 69 parser["name"] = o 70 self.assertEquals("Hello Chris", parser.merge(template)) 50 self.assertEquals("Hello Chris", template.merge({"name": o})) 71 51 72 52 def test_can_return_value_from_a_method_of_a_context_object(self): 73 parser = airspeed.Parser()74 53 template = airspeed.Template("Hello $name.first_name()") 75 54 class MyObj: 76 55 def first_name(self): return "Chris" 77 parser["name"] = MyObj() 78 self.assertEquals("Hello Chris", parser.merge(template)) 56 self.assertEquals("Hello Chris", template.merge({"name": MyObj()})) 79 57 80 58 def test_when_if_statement_resolves_to_true_the_content_is_returned(self): 81 parser = airspeed.Parser()82 59 template = airspeed.Template("Hello #if ($name)your name is ${name}#end Good to see you") 83 parser["name"] = "Steve" 84 self.assertEquals("Hello your name is Steve Good to see you", parser.merge(template)) 60 self.assertEquals("Hello your name is Steve Good to see you", template.merge({"name": "Steve"})) 85 61 86 62 def test_when_if_statement_resolves_to_false_the_content_is_skipped(self): 87 parser = airspeed.Parser()88 63 template = airspeed.Template("Hello #if ($show_greeting)your name is ${name}#end Good to see you") 89 parser["name"] = "Steve" 90 parser["show_greeting"] = False 91 self.assertEquals("Hello Good to see you", parser.merge(template)) 64 self.assertEquals("Hello Good to see you", template.merge({"name": "Steve", "show_greeting": False})) 92 65 93 66 def test_when_if_statement_is_nested_inside_a_successful_enclosing_if_it_gets_evaluated(self): 94 parser = airspeed.Parser()95 67 template = airspeed.Template("Hello #if ($show_greeting)your name is ${name}.#if ($is_birthday) Happy Birthday.#end#end Good to see you") 96 parser["name"] = "Steve" 97 parser["show_greeting"] = False 98 self.assertEquals("Hello Good to see you", parser.merge(template)) 99 parser["show_greeting"] = True 100 self.assertEquals("Hello your name is Steve. Good to see you", parser.merge(template)) 101 parser["is_birthday"] = True 102 self.assertEquals("Hello your name is Steve. Happy Birthday. Good to see you", parser.merge(template)) 68 namespace = {"name": "Steve", "show_greeting": False} 69 self.assertEquals("Hello Good to see you", template.merge(namespace)) 70 namespace["show_greeting"] = True 71 self.assertEquals("Hello your name is Steve. Good to see you", template.merge(namespace)) 72 namespace["is_birthday"] = True 73 self.assertEquals("Hello your name is Steve. Happy Birthday. Good to see you", template.merge(namespace)) 103 74 104 75 def test_new_lines_in_templates_are_permitted(self): 105 parser = airspeed.Parser()106 76 template = airspeed.Template("hello #if ($show_greeting)${name}.\n#if($is_birthday)Happy Birthday\n#end.\n#endOff out later?") 107 parser["name"] = "Steve" 108 parser["show_greeting"] = True 109 parser["is_birthday"] = True 110 self.assertEquals("hello Steve.\nHappy Birthday\n.\nOff out later?", parser.merge(template)) 77 namespace = {"name": "Steve", "show_greeting": True, "is_birthday": True} 78 self.assertEquals("hello Steve.\nHappy Birthday\n.\nOff out later?", template.merge(namespace)) 111 79 112 80 def test_foreach_with_plain_content_loops_correctly(self): 113 parser = airspeed.Parser()114 81 template = airspeed.Template("#foreach ($name in $names)Hello you. #end") 115 parser["names"] = ["Chris", "Steve"] 116 self.assertEquals("Hello you. Hello you. ", parser.merge(template)) 82 self.assertEquals("Hello you. Hello you. ", template.merge({"names": ["Chris", "Steve"]})) 117 83 118 84 def test_foreach_skipped_when_nested_in_a_failing_if(self): 119 parser = airspeed.Parser()120 85 template = airspeed.Template("#if ($false_value)#foreach ($name in $names)Hello you. #end#end") 121 parser["false_value"] = False 122 parser["names"] = ["Chris", "Steve"] 123 self.assertEquals("", parser.merge(template)) 86 self.assertEquals("", template.merge({"false_value": False, "names": ["Chris", "Steve"]})) 124 87 125 88 def test_foreach_with_expression_content_loops_correctly(self): 126 parser = airspeed.Parser()127 89 template = airspeed.Template("#foreach ($name in $names)Hello $you. #end") 128 parser["you"] = "You" 129 parser["names"] = ["Chris", "Steve"] 130 self.assertEquals("Hello You. Hello You. ", parser.merge(template)) 90 self.assertEquals("Hello You. Hello You. ", template.merge({"you": "You", "names": ["Chris", "Steve"]})) 131 91 132 92 def test_foreach_makes_loop_variable_accessible(self): 133 parser = airspeed.Parser()134 93 template = airspeed.Template("#foreach ($name in $names)Hello $name. #end") 135 parser["names"] = ["Chris", "Steve"] 136 self.assertEquals("Hello Chris. Hello Steve. ", parser.merge(template)) 94 self.assertEquals("Hello Chris. Hello Steve. ", template.merge({"names": ["Chris", "Steve"]})) 137 95 138 96 def test_loop_variable_not_accessible_after_loop(self): 139 parser = airspeed.Parser()140 97 template = airspeed.Template("#foreach ($name in $names)Hello $name. #end$name") 141 parser["names"] = ["Chris", "Steve"] 142 self.assertEquals("Hello Chris. Hello Steve. $name", parser.merge(template)) 98 self.assertEquals("Hello Chris. Hello Steve. $name", template.merge({"names": ["Chris", "Steve"]})) 143 99 144 100 def test_loop_variables_do_not_clash_in_nested_loops(self): 145 parser = airspeed.Parser()146 101 template = airspeed.Template("#foreach ($word in $greetings)$word to#foreach ($word in $names) $word#end. #end") 147 parser["greetings"] = ["Hello", "Goodbye"] 148 parser["names"] = ["Chris", "Steve"] 149 self.assertEquals("Hello to Chris Steve. Goodbye to Chris Steve. ", parser.merge(template)) 102 namespace = {"greetings": ["Hello", "Goodbye"], "names": ["Chris", "Steve"]} 103 self.assertEquals("Hello to Chris Steve. Goodbye to Chris Steve. ", template.merge(namespace)) 150 104 151 105
