Changeset 29
- Timestamp:
- 23/08/04 12:57:25 (4 years ago)
- Files:
-
- trunk/airspeed.py (modified) (8 diffs)
- trunk/airspeed_test.py (modified) (3 diffs, 1 prop)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/airspeed.py
r28 r29 1 1 #!/usr/bin/env python 2 2 3 import re, operator 3 import re, operator, os 4 4 5 5 try: import cStringIO as StringIO 6 6 except ImportError: import StringIO 7 7 8 __all__ = ['Template', 'TemplateError', 'TemplateSyntaxError', ' FileLoader']8 __all__ = ['Template', 'TemplateError', 'TemplateSyntaxError', 'CachingFileLoader'] 9 9 10 10 … … 23 23 return output.getvalue() 24 24 25 def ensure_compiled(self): 26 if not self.root_element: 27 self.root_element = TemplateBody(self.content) 28 25 29 def merge_to(self, namespace, fileobj, loader=None): 26 30 if loader is None: loader = NullLoader() 27 if not self.root_element: 28 self.root_element = TemplateBody(self.content) 31 self.ensure_compiled() 29 32 self.root_element.evaluate(namespace, fileobj, loader) 30 33 … … 64 67 65 68 66 class FileLoader:69 class CachingFileLoader: 67 70 def __init__(self, basedir): 68 71 self.basedir = basedir 72 self.known_templates = {} # name -> (template, file_mod_time) 73 74 def filename_of(self, name): 75 return os.path.join(self.basedir, name) 69 76 70 77 def load_text(self, name): 71 import os72 78 f = open(os.path.join(self.basedir, name)) 73 79 try: return f.read() … … 75 81 76 82 def load_template(self, name): 77 return Template(self.load_text(name)) 83 mtime = os.path.getmtime(self.filename_of(name)) 84 if name in self.known_templates: 85 template, prev_mtime = self.known_templates[name] 86 if mtime <= prev_mtime: 87 return template 88 template = Template(self.load_text(name)) 89 template.ensure_compiled() 90 self.known_templates[name] = (template, mtime) 91 return template 78 92 79 93 … … 216 230 217 231 232 class RangeLiteral(_Element): 233 RANGE = re.compile(r'\[[ \t]*(\-?\d+)[ \t]*\.\.[ \t]*(\-?\d+)[ \t]*\](.*)$') 234 235 def parse(self): 236 self.value1, self.value2 = map(int, self.identity_match(self.RANGE)) 237 238 def calculate(self, namespace): 239 if self.value2 < self.value1: 240 return xrange(self.value1, self.value2 - 1, -1) 241 return xrange(self.value1, self.value2 + 1) 242 243 218 244 class Value(_Element): 219 245 def parse(self): 220 self.expression = self.next_element((SimpleReference, IntegerLiteral, StringLiteral, SingleQuotedStringLiteral ))246 self.expression = self.next_element((SimpleReference, IntegerLiteral, StringLiteral, SingleQuotedStringLiteral, RangeLiteral)) 221 247 222 248 def calculate(self, namespace): … … 234 260 235 261 def calculate(self, current_object, top_namespace): 236 try: result = getattr(current_object, self.name) 237 except AttributeError: 262 look_in_dict = True 263 if not isinstance(current_object, LocalNamespace): 264 try: 265 result = getattr(current_object, self.name) 266 look_in_dict = False 267 except AttributeError: 268 pass 269 if look_in_dict: 238 270 try: result = current_object[self.name] 239 271 except KeyError: result = None … … 423 455 def parse(self): 424 456 self.var_name, = self.identity_match(self.START) 425 self.value = self. next_element(Value)457 self.value = self.require_next_element(Value, "value") 426 458 self.require_match(self.END, ')') 427 459 … … 556 588 iterable = self.value.calculate(namespace) 557 589 counter = 1 558 for item in iterable: 559 namespace = LocalNamespace(namespace) 560 namespace['velocityCount'] = counter 561 namespace[self.loop_var_name] = item 562 self.block.evaluate(namespace, stream, loader) 563 counter += 1 590 try: 591 for item in iterable: 592 namespace = LocalNamespace(namespace) 593 namespace['velocityCount'] = counter 594 namespace[self.loop_var_name] = item 595 self.block.evaluate(namespace, stream, loader) 596 counter += 1 597 except TypeError: 598 print iterable 599 raise 564 600 565 601 trunk/airspeed_test.py
- Property svn:executable set to *
r28 r29 371 371 self.assertEquals('Message is: hola!', template.merge({'foo': 'foo.tmpl', 'message': 'hola'}, loader=WorkingLoader())) 372 372 373 def test_assign_range_literal(self): 374 template = airspeed.Template('#set($values = [1..5])#foreach($value in $values)$value,#end') 375 self.assertEquals('1,2,3,4,5,', template.merge({})) 376 template = airspeed.Template('#set($values = [2..-2])#foreach($value in $values)$value,#end') 377 self.assertEquals('2,1,0,-1,-2,', template.merge({})) 378 379 def test_local_namespace_methods_not_available(self): 380 template = airspeed.Template('#macro(tryme)$values#end#tryme()') 381 self.assertEquals('$values', template.merge({})) 382 373 383 # 374 384 # TODO: … … 379 389 # list literals 380 390 # Bind #macro calls at compile time? 391 # #stop ? 381 392 # Interpolated strings 382 393 # Directives inside string literals … … 385 396 # Q. What is scope of #set ($customer.Name = 'john') ??? 386 397 # Scope of #set across if/elseif/else? 387 # Scope of namespace for # include etc398 # Scope of namespace for #parse etc 388 399 # 389 400
