Mercurial > genshi > mirror
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. |