comparison markup/template.py @ 154:8bd5c8cd33e0 trunk

* Make sure `py:def` macros don't go out of scope if they are defined inside another directive. * Cleaned up the `DefDirective` implementation a bit.
author cmlenz
date Wed, 16 Aug 2006 14:04:30 +0000
parents fc2ff46d1ae3
children 47433aa69169
comparison
equal deleted inserted replaced
153:fc2ff46d1ae3 154:8bd5c8cd33e0
288 <p class="message"> 288 <p class="message">
289 Hello, world! 289 Hello, world!
290 </p> 290 </p>
291 </div> 291 </div>
292 """ 292 """
293 __slots__ = ['name', 'args', 'defaults', 'stream', 'directives'] 293 __slots__ = ['name', 'args', 'defaults']
294 294
295 ATTRIBUTE = 'function' 295 ATTRIBUTE = 'function'
296 296
297 def __init__(self, args, filename=None, lineno=-1, offset=-1): 297 def __init__(self, args, filename=None, lineno=-1, offset=-1):
298 Directive.__init__(self, None, filename, lineno, offset) 298 Directive.__init__(self, None, filename, lineno, offset)
307 self.defaults[arg.name] = arg.expr.value 307 self.defaults[arg.name] = arg.expr.value
308 else: 308 else:
309 self.args.append(arg.name) 309 self.args.append(arg.name)
310 else: 310 else:
311 self.name = ast.name 311 self.name = ast.name
312 self.stream, self.directives = [], [] 312
313 313 def __call__(self, stream, ctxt, directives):
314 def __call__(self, stream, ctxt, directives): 314 stream = list(stream)
315 self.stream = list(stream) 315
316 self.directives = directives 316 def function(*args, **kwargs):
317 ctxt[self.name] = lambda *args, **kwargs: self._exec(ctxt, *args, 317 scope = {}
318 **kwargs) 318 args = list(args) # make mutable
319 for name in self.args:
320 if args:
321 scope[name] = args.pop(0)
322 else:
323 scope[name] = kwargs.pop(name, self.defaults.get(name))
324 ctxt.push(scope)
325 for event in _apply_directives(stream, ctxt, directives):
326 yield event
327 ctxt.pop()
328 try:
329 function.__name__ = self.name
330 except TypeError:
331 # Function name can't be set in Python 2.3
332 pass
333
334 # Store the function reference in the bottom context frame so that it
335 # doesn't get popped off before processing the template has finished
336 ctxt.frames[-1][self.name] = function
337
319 return [] 338 return []
320
321 def _exec(self, ctxt, *args, **kwargs):
322 scope = {}
323 args = list(args) # make mutable
324 for name in self.args:
325 if args:
326 scope[name] = args.pop(0)
327 else:
328 scope[name] = kwargs.pop(name, self.defaults.get(name))
329 ctxt.push(scope)
330 for event in _apply_directives(self.stream, ctxt, self.directives):
331 yield event
332 ctxt.pop()
333 339
334 340
335 class ForDirective(Directive): 341 class ForDirective(Directive):
336 """Implementation of the `py:for` template directive for repeating an 342 """Implementation of the `py:for` template directive for repeating an
337 element based on an iterable in the context data. 343 element based on an iterable in the context data.
Copyright (C) 2012-2017 Edgewall Software