frame.symbols.analyze_node(node)
self.writeline('%s(%s):' % (self.func('macro'), ', '.join(args)), node)
self.indent()
+
self.buffer(frame)
self.enter_frame(frame)
+
+ for idx, arg in enumerate(node.args):
+ self.writeline('if %s is missing:' % frame.symbols.ref(arg.name))
+ self.indent()
+ try:
+ default = node.defaults[idx - len(node.args)]
+ except IndexError:
+ self.writeline('%s = undefined(%r, name=%r)' % (
+ frame.symbols.ref(arg.name),
+ 'parameter %r was not provided' % arg.name,
+ arg.name))
+ else:
+ self.writeline('%s = ' % frame.symbols.ref(arg.name))
+ self.visit(default, frame)
+ self.outdent()
+
self.blockvisit(node.body, frame)
self.return_buffer_contents(frame)
self.leave_frame(frame, with_python_scope=True)
name = getattr(macro_ref.node, 'name', None)
if len(macro_ref.node.args) == 1:
arg_tuple += ','
- self.write('Macro(environment, macro, %r, (%s), (' %
- (name, arg_tuple))
- for arg in macro_ref.node.defaults:
- self.visit(arg, frame)
- self.write(', ')
- self.write('), %r, %r, %r)' % (
- bool(macro_ref.accesses_kwargs),
- bool(macro_ref.accesses_varargs),
- bool(macro_ref.accesses_caller)
- ))
+ self.write('Macro(environment, macro, %r, (%s), %r, %r, %r)' %
+ (name, arg_tuple, macro_ref.accesses_kwargs,
+ macro_ref.accesses_varargs, macro_ref.accesses_caller))
def position(self, node):
"""Return a human readable position for the node."""
class Macro(object):
"""Wraps a macro function."""
- def __init__(self, environment, func, name, arguments, defaults,
+ def __init__(self, environment, func, name, arguments,
catch_kwargs, catch_varargs, caller):
self._environment = environment
self._func = func
self._argument_count = len(arguments)
self.name = name
self.arguments = arguments
- self.defaults = defaults
self.catch_kwargs = catch_kwargs
self.catch_varargs = catch_varargs
self.caller = caller
try:
value = kwargs.pop(name)
except KeyError:
- try:
- value = self.defaults[idx - self._argument_count + off]
- except IndexError:
- value = self._environment.undefined(
- 'parameter %r was not provided' % name, name=name)
+ value = missing
arguments.append(value)
# it's important that the order of these arguments does not change
'{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
'{% macro baz() %}{{ caller() }}{% endmacro %}')
assert tmpl.module.foo.arguments == ('a', 'b')
- assert tmpl.module.foo.defaults == ()
assert tmpl.module.foo.name == 'foo'
assert not tmpl.module.foo.caller
assert not tmpl.module.foo.catch_kwargs
assert not tmpl.module.foo.catch_varargs
assert tmpl.module.bar.arguments == ()
- assert tmpl.module.bar.defaults == ()
assert not tmpl.module.bar.caller
assert tmpl.module.bar.catch_kwargs
assert tmpl.module.bar.catch_varargs
env = Environment()
env.globals['get_int'] = lambda: 42
t = env.from_string('''
- {% macro test(arg1=get_int()) %}
- {{ arg1 }}
- {% endmacro %}
- {{ test(1) }}|{{ test() }}
+ {% macro test(a, b, c=get_int()) -%}
+ {{ a + b + c }}
+ {%- endmacro %}
+ {{ test(1, 2) }}|{{ test(1, 2, 3) }}
''')
- assert t.render().strip() == '1|42'
+ assert t.render().strip() == '45|6'