Skip to content

Instantly share code, notes, and snippets.

@akho
Created July 14, 2009 20:08
Show Gist options
  • Save akho/147154 to your computer and use it in GitHub Desktop.
Save akho/147154 to your computer and use it in GitHub Desktop.
from django import template
def __is_quoted(str):
return (str[0] == str[-1] and str[0] in ('"', "'"))
def __process_quoted(tag_name, str):
if not __is_quoted(str):
raise template.TemplateSyntaxError("%r tag's argument %s should be in quotes" % (tag_name, str))
return str[1:-1]
sig_funcs = {
'quoted': __process_quoted,
'var': lambda t_n, c: template.Variable(c),
'plain': lambda t_n, c: c,
'int': lambda t_n, c: int(c),
}
def __parse_signature(sig_text):
sig_array = [x.strip() for x in sig_text.split(',')]
return sig_array
def tag_signature(sig_text, func=None):
"""Build a compiler function for a tag with the specified argument types.
Required argument:
sig_text -- tag's signature; format explained below
Optional keyword argument:
func -- function which takes the parameters described by sig_text; if this
is present, tag_signature returns a compiler function.
Otherwise--a decorator. (See usage examples below)
Signature syntax
sig_text must be a string containing a comma-separated list of expected
variable types, where variable types are:
quoted -- a string in single or double quotes, like 'this' or "this";
the compiler function will check that the quotes are present and then
remove them
var -- variable name
plain -- no processing, the compiler function will recieve this string as is
int -- integer, will be converted to an int
Examples:
@register.tag('some_tag')
@tag_signature('var,quoted')
def some_tag(parser, object_var, unquoted_string):
pass
Or, equivalently:
register.tag('some_tag', tag_signature('var,quoted', some_tag))
Then, in your templates:
{% some_tag variable "string" %}
"""
sig_array = __parse_signature(sig_text)
def decorator(func):
def decorated(parser, token):
params = token.split_contents()
tag_name = params[0]
params = params[1:]
if len(params) != len(sig_array):
raise template.TemplateSyntaxError("%r tag requires %i arguments" % (tag_name, len(params)))
args = []
for (sig, content) in zip(sig_array, params):
try:
args.append(sig_funcs[sig](tag_name, content))
except KeyError:
raise ValueError("tag_signature's parameter must be of the form 'sig,sig,sig', where sigs are from %s" % (', '.join(keys(sig_funcs))))
return func(parser, *args)
return decorated
if func:
return decorator(func)
else:
return decorator
def tag_compiler_for_node(node_class, signature):
"""Generate simple compiler functions for Node classes using tag_signature.
Generated compiler function returns a node_class object constructed with
parameters from the tag, parsed by signature. Format of the signature is the same
as in tag_signature.
Example:
register.tag('some_tag', tag_compiler_for_node(SomeNode, 'var,quoted'))
"""
def func(parser, *args):
return node_class(*args)
return tag_signature(signature, func)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment