Changeset 10
- Timestamp:
- 12/08/04 13:12:04 (4 years ago)
- Files:
-
- trunk/airspeed.py (modified) (7 diffs)
- trunk/airspeed_test.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/airspeed.py
r9 r10 4 4 import cStringIO as StringIO 5 5 6 6 7 class TemplateSyntaxError(Exception): pass 7 8 8 9 class Tokeniser: 9 PLAIN, IF, PLACEHOLDER, FOREACH, END = range(5)10 PLAIN, IF, PLACEHOLDER, FOREACH, END, SET = range(6) 10 11 11 12 UP_TO_NEXT_TEMPLATE_BIT = re.compile('^(.*?)((?:#|\$).*)', re.MULTILINE + re.DOTALL) … … 15 16 EXPRESSION = '(' + NAME_OR_CALL + '(?:\.' + NAME_OR_CALL + ')*)' 16 17 PLACEHOLDER_PATTERN = re.compile('^\$(!?)({?)' + EXPRESSION + '(}?)' + REST, re.IGNORECASE + re.DOTALL + re.MULTILINE) 18 SET_PATTERN = re.compile('^#set[ \t]*\([ \t]*\$(' + NAME + ')[ \t]*=[ \t]*(\d+)[ \t]*\)' + REST, re.IGNORECASE + re.DOTALL + re.MULTILINE) 17 19 BEGIN_IF_PATTERN = re.compile('^#if[ \t]*\([ \t]*\$' + EXPRESSION + '[ \t]*\)' + REST, re.IGNORECASE + re.DOTALL + re.MULTILINE) 18 20 BEGIN_FOREACH_PATTERN = re.compile('^#foreach[ \t]*\([ \t]*\$(' + NAME + ')[ \t]+in[ \t]+\$' + EXPRESSION + '[ \t]*\)' + REST, re.IGNORECASE + re.DOTALL + re.MULTILINE) … … 46 48 yield self.END, None 47 49 (text,) = m.groups() 50 continue 51 m = self.SET_PATTERN.match(interesting) 52 if m: 53 (var_name, rvalue, text) = m.groups() 54 yield self.SET, (var_name, rvalue) 55 continue 56 if interesting.startswith('$'): 57 text = interesting[1:] 58 yield self.PLAIN, '$' 48 59 continue 49 60 raise TemplateSyntaxError("invalid token: %s" % text[:40]) … … 93 104 94 105 def evaluate(self, output_stream, namespace): 106 self.evaluate_block(output_stream, BlockEvaluator.LocalNamespace(namespace)) 107 108 def evaluate_block(self, output_stream, namespace): 95 109 for child in self.children: 96 110 child.evaluate(output_stream, namespace) … … 116 130 elif token_type == Tokeniser.FOREACH: self.add_evaluator(ForeachEvaluator(token_value)) 117 131 elif token_type == Tokeniser.IF: self.add_evaluator(IfEvaluator(token_value)) 132 elif token_type == Tokeniser.SET: self.add_evaluator(SetEvaluator(token_value)) 118 133 else: raise TemplateSyntaxError("illegal token in block: %s, %s" % (token_type, token_value)) 119 134 return True … … 147 162 self.condition_expression = token_value 148 163 149 def evaluate (self, output_stream, namespace):164 def evaluate_block(self, output_stream, namespace): 150 165 value = self.eval_expression(self.condition_expression, namespace) 151 166 if value: 152 BlockEvaluator.evaluate (self, output_stream, namespace)167 BlockEvaluator.evaluate_block(self, output_stream, namespace) 153 168 154 169 … … 158 173 self.expression, self.iter_var = token_value 159 174 160 def evaluate (self, output_stream, namespace):175 def evaluate_block(self, output_stream, namespace): 161 176 values = self.eval_expression(self.expression, namespace) 162 177 counter = 1 163 178 for value in values: 164 local_namespace = BlockEvaluator.LocalNamespace(namespace) 165 local_namespace[self.iter_var] = value 166 local_namespace['velocityCount'] = counter 167 BlockEvaluator.evaluate(self, output_stream, local_namespace) 179 namespace[self.iter_var] = value 180 namespace['velocityCount'] = counter 181 BlockEvaluator.evaluate_block(self, output_stream, namespace) 168 182 counter += 1 183 184 185 class SetEvaluator(Evaluator): 186 def __init__(self, token_value): 187 self.var_name, self.rvalue = token_value 188 189 def evaluate(self, output_stream, namespace): 190 namespace[self.var_name] = int(self.rvalue) 169 191 170 192 trunk/airspeed_test.py
r9 r10 14 14 template = airspeed.Template("Hello $name") 15 15 self.assertEquals("Hello Chris", template.merge({"name": "Chris"})) 16 17 def test_dollar_left_untouched(self): 18 template = airspeed.Template("Hello $ ") 19 self.assertEquals("Hello $ ", template.merge({})) 16 20 17 21 def test_unmatched_name_does_not_get_substituted(self): … … 109 113 110 114 def test_loop_counter_variables_do_not_clash_in_nested_loops(self): 111 template = airspeed.Template("#foreach ($word in $greetings) outer $velocityCount#foreach ($word in $names), inner $velocityCount#end. #end")115 template = airspeed.Template("#foreach ($word in $greetings)Outer $velocityCount#foreach ($word in $names), inner $velocityCount#end. #end") 112 116 namespace = {"greetings": ["Hello", "Goodbye"], "names": ["Chris", "Steve"]} 113 self.assertEquals("outer 1, inner 1, inner 2. outer 2, inner 1, inner 2. ", template.merge(namespace)) 117 self.assertEquals("Outer 1, inner 1, inner 2. Outer 2, inner 1, inner 2. ", template.merge(namespace)) 118 119 def test_can_use_an_integer_variable_defined_in_template(self): 120 template = airspeed.Template("#set ($value = 10)$value") 121 self.assertEquals("10", template.merge({})) 122 123 def test_passed_in_namespace_not_modified_by_set(self): 124 template = airspeed.Template("#set ($value = 10)$value") 125 namespace = {} 126 template.merge(namespace) 127 self.assertEquals({}, namespace) 114 128 115 129
