Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / templatetags / astakos_tags.py @ 9202a57d

History | View | Annotate | Download (10.7 kB)

1 dd5f8f4d Kostas Papadimitriou
# Copyright 2011 GRNET S.A. All rights reserved.
2 dd5f8f4d Kostas Papadimitriou
#
3 dd5f8f4d Kostas Papadimitriou
# Redistribution and use in source and binary forms, with or
4 dd5f8f4d Kostas Papadimitriou
# without modification, are permitted provided that the following
5 dd5f8f4d Kostas Papadimitriou
# conditions are met:
6 dd5f8f4d Kostas Papadimitriou
#
7 dd5f8f4d Kostas Papadimitriou
#   1. Redistributions of source code must retain the above
8 dd5f8f4d Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
9 dd5f8f4d Kostas Papadimitriou
#      disclaimer.
10 dd5f8f4d Kostas Papadimitriou
#
11 dd5f8f4d Kostas Papadimitriou
#   2. Redistributions in binary form must reproduce the above
12 dd5f8f4d Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
13 dd5f8f4d Kostas Papadimitriou
#      disclaimer in the documentation and/or other materials
14 dd5f8f4d Kostas Papadimitriou
#      provided with the distribution.
15 dd5f8f4d Kostas Papadimitriou
#
16 dd5f8f4d Kostas Papadimitriou
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 dd5f8f4d Kostas Papadimitriou
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 dd5f8f4d Kostas Papadimitriou
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 dd5f8f4d Kostas Papadimitriou
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 dd5f8f4d Kostas Papadimitriou
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 dd5f8f4d Kostas Papadimitriou
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 dd5f8f4d Kostas Papadimitriou
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 dd5f8f4d Kostas Papadimitriou
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 dd5f8f4d Kostas Papadimitriou
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 dd5f8f4d Kostas Papadimitriou
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 dd5f8f4d Kostas Papadimitriou
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 dd5f8f4d Kostas Papadimitriou
# POSSIBILITY OF SUCH DAMAGE.
28 dd5f8f4d Kostas Papadimitriou
#
29 dd5f8f4d Kostas Papadimitriou
# The views and conclusions contained in the software and
30 dd5f8f4d Kostas Papadimitriou
# documentation are those of the authors and should not be
31 dd5f8f4d Kostas Papadimitriou
# interpreted as representing official policies, either expressed
32 dd5f8f4d Kostas Papadimitriou
# or implied, of GRNET S.A.
33 dd5f8f4d Kostas Papadimitriou
34 dd5f8f4d Kostas Papadimitriou
import urllib
35 dd5f8f4d Kostas Papadimitriou
36 dd5f8f4d Kostas Papadimitriou
from inspect import getargspec
37 dd5f8f4d Kostas Papadimitriou
38 4f78c22c Sofia Papagiannaki
from django import template
39 c0b26605 Sofia Papagiannaki
from django.core.urlresolvers import resolve
40 4f78c22c Sofia Papagiannaki
from django.conf import settings
41 dd5f8f4d Kostas Papadimitriou
from django.template import TemplateSyntaxError, Variable
42 058b6ec7 Kostas Papadimitriou
from django.utils.translation import ugettext as _
43 734107ef Kostas Papadimitriou
from synnefo_branding.utils import render_to_string
44 058b6ec7 Kostas Papadimitriou
from django.template import RequestContext
45 058b6ec7 Kostas Papadimitriou
from django.core.urlresolvers import reverse
46 058b6ec7 Kostas Papadimitriou
from django.utils.safestring import mark_safe
47 4f78c22c Sofia Papagiannaki
48 4f78c22c Sofia Papagiannaki
register = template.Library()
49 4f78c22c Sofia Papagiannaki
50 4f78c22c Sofia Papagiannaki
MESSAGES_VIEWS_MAP = getattr(settings, 'ASTAKOS_MESSAGES_VIEWS_MAP', {
51 4f78c22c Sofia Papagiannaki
    'astakos.im.views.index': 'LOGIN_MESSAGES',
52 4f78c22c Sofia Papagiannaki
    'astakos.im.views.logout': 'LOGIN_MESSAGES',
53 4f78c22c Sofia Papagiannaki
    'astakos.im.views.login': 'LOGIN_MESSAGES',
54 4f78c22c Sofia Papagiannaki
    'astakos.im.views.signup': 'SIGNUP_MESSAGES',
55 4f78c22c Sofia Papagiannaki
    'astakos.im.views.edit_profile': 'PROFILE_MESSAGES',
56 4f78c22c Sofia Papagiannaki
    'astakos.im.views.change_password': 'PROFILE_MESSAGES',
57 4f78c22c Sofia Papagiannaki
    'astakos.im.views.invite': 'PROFILE_MESSAGES',
58 4f78c22c Sofia Papagiannaki
    'astakos.im.views.feedback': 'PROFILE_MESSAGES',
59 4f78c22c Sofia Papagiannaki
})
60 4f78c22c Sofia Papagiannaki
61 9a06d96f Olga Brani
62 dd5f8f4d Kostas Papadimitriou
# helper tag decorator
63 dd5f8f4d Kostas Papadimitriou
# https://github.com/djblets/djblets/blob/master/djblets/util/decorators.py#L96
64 dd5f8f4d Kostas Papadimitriou
def basictag(takes_context=False):
65 dd5f8f4d Kostas Papadimitriou
    """
66 dd5f8f4d Kostas Papadimitriou
    A decorator similar to Django's @register.simple_tag that optionally
67 dd5f8f4d Kostas Papadimitriou
    takes a context parameter. This condenses many tag implementations down
68 dd5f8f4d Kostas Papadimitriou
    to a few lines of code.
69 dd5f8f4d Kostas Papadimitriou

70 dd5f8f4d Kostas Papadimitriou
    Example:
71 dd5f8f4d Kostas Papadimitriou
        @register.tag
72 dd5f8f4d Kostas Papadimitriou
        @basictag(takes_context=True)
73 dd5f8f4d Kostas Papadimitriou
        def printuser(context):
74 dd5f8f4d Kostas Papadimitriou
            return context['user']
75 dd5f8f4d Kostas Papadimitriou
    """
76 dd5f8f4d Kostas Papadimitriou
    class BasicTagNode(template.Node):
77 dd5f8f4d Kostas Papadimitriou
        def __init__(self, take_context, tag_name, tag_func, args):
78 dd5f8f4d Kostas Papadimitriou
            self.takes_context = takes_context
79 dd5f8f4d Kostas Papadimitriou
            self.tag_name = tag_name
80 dd5f8f4d Kostas Papadimitriou
            self.tag_func = tag_func
81 dd5f8f4d Kostas Papadimitriou
            self.args = args
82 dd5f8f4d Kostas Papadimitriou
83 dd5f8f4d Kostas Papadimitriou
        def render(self, context):
84 dd5f8f4d Kostas Papadimitriou
            args = [Variable(var).resolve(context) for var in self.args]
85 dd5f8f4d Kostas Papadimitriou
86 dd5f8f4d Kostas Papadimitriou
            if self.takes_context:
87 dd5f8f4d Kostas Papadimitriou
                return self.tag_func(context, *args)
88 dd5f8f4d Kostas Papadimitriou
            else:
89 dd5f8f4d Kostas Papadimitriou
                return self.tag_func(*args)
90 dd5f8f4d Kostas Papadimitriou
91 dd5f8f4d Kostas Papadimitriou
    def basictag_func(tag_func):
92 dd5f8f4d Kostas Papadimitriou
        def _setup_tag(parser, token):
93 dd5f8f4d Kostas Papadimitriou
            bits = token.split_contents()
94 dd5f8f4d Kostas Papadimitriou
            tag_name = bits[0]
95 dd5f8f4d Kostas Papadimitriou
            del(bits[0])
96 dd5f8f4d Kostas Papadimitriou
97 dd5f8f4d Kostas Papadimitriou
            params, xx, xxx, defaults = getargspec(tag_func)
98 dd5f8f4d Kostas Papadimitriou
            max_args = len(params)
99 dd5f8f4d Kostas Papadimitriou
100 dd5f8f4d Kostas Papadimitriou
            if takes_context:
101 dd5f8f4d Kostas Papadimitriou
                if params[0] == 'context':
102 8fb8d0cf Giorgos Korfiatis
                    max_args -= 1  # Ignore context
103 dd5f8f4d Kostas Papadimitriou
                else:
104 8fb8d0cf Giorgos Korfiatis
                    m = "Any tag function decorated with takes_context=True " \
105 dd5f8f4d Kostas Papadimitriou
                        "must have a first argument of 'context'"
106 8fb8d0cf Giorgos Korfiatis
                    raise TemplateSyntaxError(m)
107 dd5f8f4d Kostas Papadimitriou
108 dd5f8f4d Kostas Papadimitriou
            min_args = max_args - len(defaults or [])
109 dd5f8f4d Kostas Papadimitriou
110 dd5f8f4d Kostas Papadimitriou
            if not min_args <= len(bits) <= max_args:
111 dd5f8f4d Kostas Papadimitriou
                if min_args == max_args:
112 8fb8d0cf Giorgos Korfiatis
                    m = "%r tag takes %d arguments." % (tag_name, min_args)
113 8fb8d0cf Giorgos Korfiatis
                    raise TemplateSyntaxError(m)
114 dd5f8f4d Kostas Papadimitriou
                else:
115 8fb8d0cf Giorgos Korfiatis
                    m = "%r tag takes %d to %d arguments, got %d." % \
116 dd5f8f4d Kostas Papadimitriou
                        (tag_name, min_args, max_args, len(bits))
117 8fb8d0cf Giorgos Korfiatis
                    raise TemplateSyntaxError(m)
118 dd5f8f4d Kostas Papadimitriou
119 dd5f8f4d Kostas Papadimitriou
            return BasicTagNode(takes_context, tag_name, tag_func, bits)
120 dd5f8f4d Kostas Papadimitriou
121 dd5f8f4d Kostas Papadimitriou
        _setup_tag.__name__ = tag_func.__name__
122 dd5f8f4d Kostas Papadimitriou
        _setup_tag.__doc__ = tag_func.__doc__
123 dd5f8f4d Kostas Papadimitriou
        _setup_tag.__dict__.update(tag_func.__dict__)
124 dd5f8f4d Kostas Papadimitriou
        return _setup_tag
125 dd5f8f4d Kostas Papadimitriou
126 dd5f8f4d Kostas Papadimitriou
    return basictag_func
127 dd5f8f4d Kostas Papadimitriou
128 dd5f8f4d Kostas Papadimitriou
129 4f78c22c Sofia Papagiannaki
@register.tag(name='display_messages')
130 4f78c22c Sofia Papagiannaki
def display_messages(parser, token):
131 4f78c22c Sofia Papagiannaki
    return MessagesNode()
132 4f78c22c Sofia Papagiannaki
133 9a06d96f Olga Brani
134 4f78c22c Sofia Papagiannaki
class DummyMessage(object):
135 4f78c22c Sofia Papagiannaki
    def __init__(self, type, msg):
136 4f78c22c Sofia Papagiannaki
        self.message = msg
137 4f78c22c Sofia Papagiannaki
        self.tags = type
138 4f78c22c Sofia Papagiannaki
139 4f78c22c Sofia Papagiannaki
    def __repr__(self):
140 4f78c22c Sofia Papagiannaki
        return "%s: %s" % (self.tags, self.message)
141 4f78c22c Sofia Papagiannaki
142 9a06d96f Olga Brani
143 4f78c22c Sofia Papagiannaki
class MessagesNode(template.Node):
144 4f78c22c Sofia Papagiannaki
145 4f78c22c Sofia Papagiannaki
    def get_view_messages(self, context):
146 4f78c22c Sofia Papagiannaki
        messages = list(context['GLOBAL_MESSAGES'])
147 4f78c22c Sofia Papagiannaki
        try:
148 4f78c22c Sofia Papagiannaki
            view = resolve(context['request'].get_full_path())[0]
149 4f78c22c Sofia Papagiannaki
            view_name = "%s.%s" % (view.__module__, view.func_name)
150 4f78c22c Sofia Papagiannaki
            messages += context[MESSAGES_VIEWS_MAP.get(view_name)]
151 4f78c22c Sofia Papagiannaki
            return messages
152 4f78c22c Sofia Papagiannaki
        except Exception, e:
153 4f78c22c Sofia Papagiannaki
            return messages
154 4f78c22c Sofia Papagiannaki
155 4f78c22c Sofia Papagiannaki
    def render(self, context):
156 4f78c22c Sofia Papagiannaki
        if self not in context.render_context:
157 4f78c22c Sofia Papagiannaki
            messages = list(context['messages'])
158 4f78c22c Sofia Papagiannaki
            if context['EXTRA_MESSAGES_SET']:
159 4f78c22c Sofia Papagiannaki
                view_messages = self.get_view_messages(context)
160 4f78c22c Sofia Papagiannaki
                for msg_object in view_messages:
161 4f78c22c Sofia Papagiannaki
                    messages.append(DummyMessage(msg_object[0], msg_object[1]))
162 4f78c22c Sofia Papagiannaki
163 4f78c22c Sofia Papagiannaki
            if not messages:
164 4f78c22c Sofia Papagiannaki
                return ""
165 4f78c22c Sofia Papagiannaki
166 4f78c22c Sofia Papagiannaki
            cls = messages[-1].tags
167 4f78c22c Sofia Papagiannaki
            content = '<div class="top-msg active %s">' % cls
168 4f78c22c Sofia Papagiannaki
            for msg in messages:
169 9a06d96f Olga Brani
                content += '<div class="msg %s">%s</div>' % (
170 9a06d96f Olga Brani
                    msg.tags, msg.message)
171 4f78c22c Sofia Papagiannaki
172 4f78c22c Sofia Papagiannaki
            content += '<a href="#" title="close" class="close">X</a>'
173 4f78c22c Sofia Papagiannaki
            content += '</div>'
174 4f78c22c Sofia Papagiannaki
            context.render_context[self] = content
175 4f78c22c Sofia Papagiannaki
176 4f78c22c Sofia Papagiannaki
        return context.render_context[self]
177 279d6e51 Olga Brani
178 279d6e51 Olga Brani
179 279d6e51 Olga Brani
@register.simple_tag
180 9efd0075 Kostas Papadimitriou
def get_grant_value(rname, project_or_app, for_project=True):
181 9efd0075 Kostas Papadimitriou
    if not project_or_app:
182 9efd0075 Kostas Papadimitriou
        return None
183 9efd0075 Kostas Papadimitriou
    resource_set = project_or_app.grants
184 9efd0075 Kostas Papadimitriou
    r = resource_set.get(resource__name=rname)
185 9efd0075 Kostas Papadimitriou
    if for_project:
186 9efd0075 Kostas Papadimitriou
        return r.project_capacity
187 9efd0075 Kostas Papadimitriou
    else:
188 9efd0075 Kostas Papadimitriou
        return r.member_capacity
189 dd5f8f4d Kostas Papadimitriou
190 8fb8d0cf Giorgos Korfiatis
191 dd5f8f4d Kostas Papadimitriou
@register.tag(name="provider_login_url")
192 dd5f8f4d Kostas Papadimitriou
@basictag(takes_context=True)
193 0e79735c Kostas Papadimitriou
def provider_login_url(context, provider, from_login=False):
194 dd5f8f4d Kostas Papadimitriou
    request = context['request'].REQUEST
195 dd5f8f4d Kostas Papadimitriou
    next = request.get('next', None)
196 dd5f8f4d Kostas Papadimitriou
    code = request.get('code', None)
197 dd5f8f4d Kostas Papadimitriou
    key = request.get('key', None)
198 dd5f8f4d Kostas Papadimitriou
199 dd5f8f4d Kostas Papadimitriou
    attrs = {}
200 dd5f8f4d Kostas Papadimitriou
    if next:
201 dd5f8f4d Kostas Papadimitriou
        attrs['next'] = next
202 dd5f8f4d Kostas Papadimitriou
    if code:
203 dd5f8f4d Kostas Papadimitriou
        attrs['code'] = code
204 dd5f8f4d Kostas Papadimitriou
    if key:
205 dd5f8f4d Kostas Papadimitriou
        attrs['key'] = key
206 0e79735c Kostas Papadimitriou
    if from_login:
207 0e79735c Kostas Papadimitriou
        attrs['from_login'] = 1
208 dd5f8f4d Kostas Papadimitriou
209 9d20fe23 Kostas Papadimitriou
    url = provider.urls.get('login')
210 dd5f8f4d Kostas Papadimitriou
211 dd5f8f4d Kostas Papadimitriou
    joinchar = "?"
212 dd5f8f4d Kostas Papadimitriou
    if "?" in url:
213 dd5f8f4d Kostas Papadimitriou
        joinchar = "&"
214 dd5f8f4d Kostas Papadimitriou
215 9d20fe23 Kostas Papadimitriou
    return "%s%s%s" % (url, joinchar, urllib.urlencode(attrs))
216 dd5f8f4d Kostas Papadimitriou
217 058b6ec7 Kostas Papadimitriou
218 058b6ec7 Kostas Papadimitriou
EXTRA_CONTENT_MAP = {
219 058b6ec7 Kostas Papadimitriou
    'confirm_text': '<textarea name="reason"></textarea>'
220 058b6ec7 Kostas Papadimitriou
}
221 058b6ec7 Kostas Papadimitriou
222 058b6ec7 Kostas Papadimitriou
CONFIRM_LINK_PROMPT_MAP = {
223 058b6ec7 Kostas Papadimitriou
    'project_modification_cancel': _('Are you sure you want to dismiss this '
224 058b6ec7 Kostas Papadimitriou
                                     'project ?'),
225 058b6ec7 Kostas Papadimitriou
    'project_app_cancel': _('Are you sure you want to cancel this project ?'),
226 058b6ec7 Kostas Papadimitriou
    'project_app_approve': _('Are you sure you want to approve this '
227 058b6ec7 Kostas Papadimitriou
                             'project ?'),
228 058b6ec7 Kostas Papadimitriou
    'project_app_deny': _('Are you sure you want to deny this project ? '
229 058b6ec7 Kostas Papadimitriou
                          '<br /><br />You '
230 058b6ec7 Kostas Papadimitriou
                          'may optionally provide denial reason in the '
231 44f2d10d Kostas Papadimitriou
                          'following field: <br /><br /><textarea '
232 44f2d10d Kostas Papadimitriou
                          'class="deny_reason" name="reason"></textarea>'),
233 058b6ec7 Kostas Papadimitriou
    'project_app_dismiss': _('Are you sure you want to dismiss this '
234 058b6ec7 Kostas Papadimitriou
                             'project ?'),
235 44f2d10d Kostas Papadimitriou
    'project_join': _('Are you sure you want to join this project ?'),
236 44f2d10d Kostas Papadimitriou
    'project_leave': _('Are you sure you want to leave from the project ?'),
237 9efd0075 Kostas Papadimitriou
    'project_cancel_member': _('Are you sure you want to cancel your join request ?'),
238 058b6ec7 Kostas Papadimitriou
}
239 058b6ec7 Kostas Papadimitriou
240 058b6ec7 Kostas Papadimitriou
241 058b6ec7 Kostas Papadimitriou
@register.tag(name="confirm_link")
242 058b6ec7 Kostas Papadimitriou
@basictag(takes_context=True)
243 058b6ec7 Kostas Papadimitriou
def confirm_link(context, title, prompt='', url=None, urlarg=None,
244 058b6ec7 Kostas Papadimitriou
                 extracontent='',
245 058b6ec7 Kostas Papadimitriou
                 confirm_prompt=None,
246 058b6ec7 Kostas Papadimitriou
                 inline=True,
247 c2b1d833 Olga Brani
                 cls='',
248 058b6ec7 Kostas Papadimitriou
                 template="im/table_rich_link_column.html"):
249 058b6ec7 Kostas Papadimitriou
250 058b6ec7 Kostas Papadimitriou
    urlargs = None
251 058b6ec7 Kostas Papadimitriou
    if urlarg:
252 b4a8228e Kostas Papadimitriou
        if isinstance(urlarg, basestring) and "," in urlarg:
253 b4a8228e Kostas Papadimitriou
            args = urlarg.split(",")
254 b4a8228e Kostas Papadimitriou
            for index, arg in enumerate(args):
255 9efd0075 Kostas Papadimitriou
                property = None
256 9efd0075 Kostas Papadimitriou
                if "." in arg:
257 9efd0075 Kostas Papadimitriou
                    arg, property = arg.split(".")
258 b4a8228e Kostas Papadimitriou
                if context.get(arg, None) is not None:
259 9efd0075 Kostas Papadimitriou
                    val = context.get(arg)
260 9efd0075 Kostas Papadimitriou
                    if property:
261 9efd0075 Kostas Papadimitriou
                        val = getattr(val, property)
262 9efd0075 Kostas Papadimitriou
                    args[index] = val
263 b4a8228e Kostas Papadimitriou
            urlargs = args
264 b4a8228e Kostas Papadimitriou
        else:
265 b4a8228e Kostas Papadimitriou
            urlargs = (urlarg,)
266 058b6ec7 Kostas Papadimitriou
267 058b6ec7 Kostas Papadimitriou
    if CONFIRM_LINK_PROMPT_MAP.get(prompt, None):
268 058b6ec7 Kostas Papadimitriou
        prompt = mark_safe(CONFIRM_LINK_PROMPT_MAP.get(prompt))
269 058b6ec7 Kostas Papadimitriou
270 c2b1d833 Olga Brani
    if url:
271 c2b1d833 Olga Brani
        url = reverse(url, args=urlargs)
272 c2b1d833 Olga Brani
    else:
273 c2b1d833 Olga Brani
        url = None
274 c2b1d833 Olga Brani
275 058b6ec7 Kostas Papadimitriou
    title = _(title)
276 058b6ec7 Kostas Papadimitriou
    tpl_context = RequestContext(context.get('request'))
277 058b6ec7 Kostas Papadimitriou
    tpl_context.update({
278 058b6ec7 Kostas Papadimitriou
        'col': {
279 058b6ec7 Kostas Papadimitriou
            'method': 'POST',
280 058b6ec7 Kostas Papadimitriou
            'cancel_prompt': 'CANCEL',
281 058b6ec7 Kostas Papadimitriou
            'confirm_prompt': confirm_prompt or title
282 058b6ec7 Kostas Papadimitriou
        },
283 058b6ec7 Kostas Papadimitriou
        'inline': inline,
284 058b6ec7 Kostas Papadimitriou
        'url': url,
285 058b6ec7 Kostas Papadimitriou
        'action': title,
286 c2b1d833 Olga Brani
        'cls': cls,
287 058b6ec7 Kostas Papadimitriou
        'prompt': prompt,
288 058b6ec7 Kostas Papadimitriou
        'extra_form_content': EXTRA_CONTENT_MAP.get(extracontent, ''),
289 058b6ec7 Kostas Papadimitriou
        'confirm': True
290 058b6ec7 Kostas Papadimitriou
    })
291 058b6ec7 Kostas Papadimitriou
292 058b6ec7 Kostas Papadimitriou
    content = render_to_string(template, tpl_context)
293 058b6ec7 Kostas Papadimitriou
    return content
294 058b6ec7 Kostas Papadimitriou
295 3f3dc4b7 Olga Brani
296 460b907d Kostas Papadimitriou
@register.simple_tag
297 3f3dc4b7 Olga Brani
def substract(arg1, arg2):
298 460b907d Kostas Papadimitriou
    return arg1 - arg2
299 460b907d Kostas Papadimitriou
300 460b907d Kostas Papadimitriou
301 4e03ba30 Kostas Papadimitriou
class VerbatimNode(template.Node):
302 4e03ba30 Kostas Papadimitriou
303 4e03ba30 Kostas Papadimitriou
    def __init__(self, text):
304 4e03ba30 Kostas Papadimitriou
        self.text = text
305 4e03ba30 Kostas Papadimitriou
306 4e03ba30 Kostas Papadimitriou
    def render(self, context):
307 4e03ba30 Kostas Papadimitriou
        return self.text
308 4e03ba30 Kostas Papadimitriou
309 4e03ba30 Kostas Papadimitriou
310 4e03ba30 Kostas Papadimitriou
@register.tag
311 4e03ba30 Kostas Papadimitriou
def verbatim(parser, token):
312 4e03ba30 Kostas Papadimitriou
    text = []
313 4e03ba30 Kostas Papadimitriou
    while 1:
314 4e03ba30 Kostas Papadimitriou
        token = parser.tokens.pop(0)
315 4e03ba30 Kostas Papadimitriou
        if token.contents == 'endverbatim':
316 4e03ba30 Kostas Papadimitriou
            break
317 4e03ba30 Kostas Papadimitriou
        if token.token_type == template.TOKEN_VAR:
318 4e03ba30 Kostas Papadimitriou
            text.append('{{')
319 4e03ba30 Kostas Papadimitriou
        elif token.token_type == template.TOKEN_BLOCK:
320 4e03ba30 Kostas Papadimitriou
            text.append('{%')
321 4e03ba30 Kostas Papadimitriou
        text.append(token.contents)
322 4e03ba30 Kostas Papadimitriou
        if token.token_type == template.TOKEN_VAR:
323 4e03ba30 Kostas Papadimitriou
            text.append('}}')
324 4e03ba30 Kostas Papadimitriou
        elif token.token_type == template.TOKEN_BLOCK:
325 4e03ba30 Kostas Papadimitriou
            text.append('%}')
326 4e03ba30 Kostas Papadimitriou
    return VerbatimNode(''.join(text))