summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorianb <devnull@localhost>2007-06-13 03:00:26 +0000
committerianb <devnull@localhost>2007-06-13 03:00:26 +0000
commit2e66fbce02c51673f6fdbb6a7f17524fa24d6478 (patch)
treebb9b9a33bfd22296f115e281704a14f54b46c156
parentec2dc54ea78b8ebbe9e0d62d0aaa6386b81ba6cb (diff)
downloadpaste-2e66fbce02c51673f6fdbb6a7f17524fa24d6478.tar.gz
Added {{default}} directive to paste.util.template
-rw-r--r--docs/news.txt3
-rw-r--r--paste/util/template.py30
-rw-r--r--tests/test_template.txt14
3 files changed, 47 insertions, 0 deletions
diff --git a/docs/news.txt b/docs/news.txt
index dc1cce3..1d7b8df 100644
--- a/docs/news.txt
+++ b/docs/news.txt
@@ -55,6 +55,9 @@ svn trunk
* Added REST methods to ``paste.fixture.TestApp``, so you can more
easily do requests like PUT and DELETE. From Anders Pearson.
+* Added ``{{default var=default_value}}`` command to
+ ``paste.util.template``
+
1.3
---
diff --git a/paste/util/template.py b/paste/util/template.py
index 4da60c8..9f44e23 100644
--- a/paste/util/template.py
+++ b/paste/util/template.py
@@ -15,6 +15,7 @@ syntax is::
def foo(bar):
return 'baz'
}}
+ {{default var = default_value}}
You use this with the ``Template`` class or the ``sub`` shortcut.
The ``Template`` class takes the template string and the name of
@@ -39,6 +40,7 @@ __all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate',
token_re = re.compile(r'\{\{|\}\}')
in_re = re.compile(r'\s+in\s+')
+var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
class TemplateError(Exception):
"""Exception raised while parsing a template
@@ -148,6 +150,11 @@ class Template(object):
func = self._eval(part, ns, pos)
base = func(base)
out.append(self._repr(base, pos))
+ elif name == 'default':
+ var, expr = code[2], code[3]
+ if var not in ns:
+ result = self._eval(expr, ns, pos)
+ ns[var] = result
else:
assert 0, "Unknown code: %r" % name
@@ -570,6 +577,8 @@ def parse_expr(tokens, name, context=()):
position=pos, name=name)
elif expr.startswith('for '):
return parse_for(tokens, name, context)
+ elif expr.startswith('default '):
+ return parse_default(tokens, name, context)
return ('expr', pos, tokens[0][0]), tokens[1:]
def parse_cond(tokens, name, context):
@@ -647,6 +656,27 @@ def parse_for(tokens, name, context):
next, tokens = parse_expr(tokens, name, context)
content.append(next)
+def parse_default(tokens, name, context):
+ first, pos = tokens[0]
+ assert first.startswith('default ')
+ first = first.split(None, 1)[1]
+ parts = first.split('=', 1)
+ if len(parts) == 1:
+ raise TemplateError(
+ "Expression must be {{default var=value}}; no = found in %r" % first,
+ position=pos, name=name)
+ var = parts[0].strip()
+ if ',' in var:
+ raise TemplateError(
+ "{{default x, y = ...}} is not supported",
+ position=pos, name=name)
+ if not var_re.search(var):
+ raise TemplateError(
+ "Not a valid variable name for {{default}}: %r"
+ % var, position=pos, name=name)
+ expr = parts[1].strip()
+ return ('default', pos, var, expr), tokens[1:]
+
_fill_command_usage = """\
%prog [OPTIONS] TEMPLATE arg=value
diff --git a/tests/test_template.txt b/tests/test_template.txt
index a56049f..7c66427 100644
--- a/tests/test_template.txt
+++ b/tests/test_template.txt
@@ -116,3 +116,17 @@ contains a directive/statement (if/for, etc)::
'x=1\n'
>>> sub('{{if 1}}\nx={{x}}\n{{endif}}\n', x=1)
'x=1\n'
+
+Lastly, there is a special directive that will create a default value
+for a variable, if no value is given::
+
+ >>> sub('{{default x=1}}{{x}}', x=2)
+ '2'
+ >>> sub('{{default x=1}}{{x}}')
+ '1'
+ >>> # The normal case:
+ >>> sub('{{x}}')
+ Traceback (most recent call last):
+ ...
+ NameError: name 'x' is not defined at line 1 column 3
+