Skip to content

Commit

Permalink
#334 Fix amend template tag context (#425)
Browse files Browse the repository at this point in the history
* #334 Fix amend template tag context

* #334 Test fixed amend template tag context
  • Loading branch information
martinmacko47 authored Apr 11, 2022
1 parent 0228618 commit c91e384
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 41 deletions.
20 changes: 11 additions & 9 deletions poleno/utils/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def get_template_sources(self, template_name, template_dirs=None):

class Library(template.Library):

def simple_pair_tag(self, func=None, takes_context=None, name=None):
def simple_pair_tag(self, func=None, takes_context=None, name=None, lazy_content=None):

def compiler(parser, token, params, varargs, varkw, defaults,
name, takes_context, node_class):
Expand All @@ -147,17 +147,19 @@ def __init__(self, takes_context, nodelist, args, kwargs):
self.args = args
self.kwargs = kwargs

def get_resolved_arguments(self, context):
def render(self, context):
resolved_args = [var.resolve(context) for var in self.args]
if self.takes_context:
resolved_args = [context] + resolved_args
resolved_args = [self.nodelist.render(context)] + resolved_args
resolved_kwargs = dict((k, v.resolve(context)) for k, v in self.kwargs.items())
return resolved_args, resolved_kwargs

def render(self, context):
resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
return func(*resolved_args, **resolved_kwargs)
if lazy_content:
content = self.nodelist.render
else:
content = self.nodelist.render(context)

if self.takes_context:
return func(content, context, *resolved_args, **resolved_kwargs)
else:
return func(content, *resolved_args, **resolved_kwargs)

params, varargs, varkw, defaults = getargspec(func)
function_name = (name or getattr(func, u'_decorated_function', func).__name__)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% load prepend from poleno.amend %}

<ul>
<li>aaa</li>
<li>bbb</li>
</ul>

{% prepend path=".//ul" %}<li>xxx</li>{% endprepend %}
{% prepend path=".//li" %}!{% endprepend %}
51 changes: 19 additions & 32 deletions poleno/utils/templatetags/poleno/amend.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def _combine_parts(parent, parts):
return parent


@register.simple_pair_tag(takes_context=True)
@register.simple_pair_tag(takes_context=True, lazy_content=True)
def amend(content, context):
u"""
Edit a snippet of HTML by parsing it, manipulating its element tree and exporting it back to
Expand All @@ -43,15 +43,14 @@ def amend(content, context):
Adds a paragraph at the beginning of each form in `template.html`.
"""
if u'_amend' not in context:
return content
with context.push():
context[u'_amend'] = []

fragment = lxml.html.fragment_fromstring(content, create_parent=u'root')
for action in context[u'_amend']:
fragment = action(fragment)
fragment = lxml.html.fragment_fromstring(content(context), create_parent=u'root')
for action in context[u'_amend']:
fragment = action(fragment)

del context[u'_amend']
return lxml.html.tostring(fragment)[6:-7] # Strip root tag
return lxml.html.tostring(fragment)[6:-7] # Strip root tag

@register.simple_pair_tag(takes_context=True)
def prepend(content, context, path):
Expand All @@ -75,9 +74,6 @@ def prepend(content, context, path):
<li>bbb</li>
</ul>
"""
if u'_amend' not in context:
context[u'_amend'] = []

def action(fragment):
elements = fragment.findall(path)
for element in elements:
Expand All @@ -87,7 +83,8 @@ def action(fragment):
_combine_parts(element, subtree_parts + element_parts)
return fragment

context[u'_amend'].append(action)
if u'_amend' in context:
context[u'_amend'].append(action)
return u''

@register.simple_pair_tag(takes_context=True)
Expand All @@ -112,9 +109,6 @@ def append(content, context, path):
<li>xxx</li>
</ul>
"""
if u'_amend' not in context:
context[u'_amend'] = []

def action(fragment):
elements = fragment.findall(path)
for element in elements:
Expand All @@ -124,7 +118,8 @@ def action(fragment):
_combine_parts(element, element_parts + subtree_parts)
return fragment

context[u'_amend'].append(action)
if u'_amend' in context:
context[u'_amend'].append(action)
return u''

@register.simple_pair_tag(takes_context=True)
Expand All @@ -151,9 +146,6 @@ def before(content, context, path):
<li>ccc</li>
</ul>
"""
if u'_amend' not in context:
context[u'_amend'] = []

def action(fragment):
elements = fragment.findall(path)
for element in elements:
Expand All @@ -166,7 +158,8 @@ def action(fragment):
parent_parts[0:2*index+1] + subtree_parts + parent_parts[2*index+1:])
return fragment

context[u'_amend'].append(action)
if u'_amend' in context:
context[u'_amend'].append(action)
return u''

@register.simple_pair_tag(takes_context=True)
Expand All @@ -193,9 +186,6 @@ def after(content, context, path):
<li>ccc</li>
</ul>
"""
if u'_amend' not in context:
context[u'_amend'] = []

def action(fragment):
elements = fragment.findall(path)
for element in elements:
Expand All @@ -208,7 +198,8 @@ def action(fragment):
parent_parts[0:2*index+2] + subtree_parts + parent_parts[2*index+2:])
return fragment

context[u'_amend'].append(action)
if u'_amend' in context:
context[u'_amend'].append(action)
return u''

@register.simple_tag(takes_context=True)
Expand All @@ -233,16 +224,14 @@ def delete(context, path):
<li>ccc</li>
</ul>
"""
if u'_amend' not in context:
context[u'_amend'] = []

def action(fragment):
elements = fragment.findall(path)
for element in elements:
element.drop_tree()
return fragment

context[u'_amend'].append(action)
if u'_amend' in context:
context[u'_amend'].append(action)
return u''

@register.simple_tag(takes_context=True)
Expand Down Expand Up @@ -275,9 +264,6 @@ def set_attributes(context, path, **kwargs):
<li aaa="1" bbb="2" ccc="0">xxx</li>
</ul>
"""
if u'_amend' not in context:
context[u'_amend'] = []

def action(fragment):
elements = fragment.findall(path)
for element in elements:
Expand All @@ -290,5 +276,6 @@ def action(fragment):
element.set(key, str(value))
return fragment

context[u'_amend'].append(action)
if u'_amend' in context:
context[u'_amend'].append(action)
return u''
111 changes: 111 additions & 0 deletions poleno/utils/tests/test_templatetags.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,26 @@ def test_set_attributes_tag(self):
u'</ul>'
u'')

def test_amend_tag_with_operation_tags_before_content(self):
rendered = self._render(
u'{% load amend prepend from poleno.amend %}'
u'{% amend %}'
u' {% prepend path=".//ul" %}<li>xxx</li>{% endprepend %}'
u' {% prepend path=".//li" %}!{% endprepend %}'
u' <ul>'
u' <li>aaa</li>'
u' <li>bbb</li>'
u' </ul>'
u'{% endamend %}'
u'')
self.assertHTMLEqual(rendered,
u'<ul>'
u' <li>!xxx</li>'
u' <li>!aaa</li>'
u' <li>!bbb</li>'
u'</ul>'
u'')

def test_amend_tag_on_plain_text(self):
rendered = self._render(
u'{% load amend prepend append from poleno.amend %}'
Expand Down Expand Up @@ -481,6 +501,21 @@ def test_amend_tag_on_multiple_tags(self):
u'<p>yyy</p>'
u'')

def test_amend_tag_on_imported_content(self):
rendered = self._render(
u'{% load amend from poleno.amend %}'
u'{% amend %}'
u' {% include "utils/tests/amendtemplatetagtest/test_amend_tag_on_imported_content.html" %}'
u'{% endamend %}'
u'')
self.assertHTMLEqual(rendered,
u'<ul>'
u' <li>!xxx</li>'
u' <li>!aaa</li>'
u' <li>!bbb</li>'
u'</ul>'
u'')

def test_multiple_amend_tags(self):
rendered = self._render(
u'{% load amend prepend append from poleno.amend %}'
Expand Down Expand Up @@ -514,6 +549,82 @@ def test_multiple_amend_tags(self):
u'</ul>'
u'')

def test_nested_amend_tags(self):
rendered = self._render(
u'{% load amend prepend append from poleno.amend %}'
u'{% amend %}'
u' <ul>'
u' <li>aaa</li>'
u' <li>bbb</li>'
u' <li>'
u' {% amend %}'
u' <ul>'
u' <li>aaa</li>'
u' <li>bbb</li>'
u' </ul>'
u' {% append path=".//ul" %}<li>yyy</li>{% endappend %}'
u' {% append path=".//li" %}?{% endappend %}'
u' {% endamend %}'
u' </li>'
u' </ul>'
u' {% prepend path=".//ul" %}<li>xxx</li>{% endprepend %}'
u' {% prepend path=".//li" %}!{% endprepend %}'
u'{% endamend %}'
u'')
self.assertHTMLEqual(rendered,
u'<ul>'
u' <li>!xxx</li>'
u' <li>!aaa</li>'
u' <li>!bbb</li>'
u' <li>!'
u' <ul>'
u' <li>!xxx</li>'
u' <li>!aaa?</li>'
u' <li>!bbb?</li>'
u' <li>!yyy?</li>'
u' </ul>'
u' </li>'
u'</ul>'
u'')

def test_nested_amend_tags_with_operation_tags_before_content(self):
rendered = self._render(
u'{% load amend prepend append from poleno.amend %}'
u'{% amend %}'
u' {% prepend path=".//ul" %}<li>xxx</li>{% endprepend %}'
u' {% prepend path=".//li" %}!{% endprepend %}'
u' <ul>'
u' <li>aaa</li>'
u' <li>bbb</li>'
u' <li>'
u' {% amend %}'
u' {% append path=".//ul" %}<li>yyy</li>{% endappend %}'
u' {% append path=".//li" %}?{% endappend %}'
u' <ul>'
u' <li>aaa</li>'
u' <li>bbb</li>'
u' </ul>'
u' {% endamend %}'
u' </li>'
u' </ul>'
u'{% endamend %}'
u'')
self.assertHTMLEqual(rendered,
u'<ul>'
u' <li>!xxx</li>'
u' <li>!aaa</li>'
u' <li>!bbb</li>'
u' <li>!'
u' <ul>'
u' <li>!xxx</li>'
u' <li>!aaa?</li>'
u' <li>!bbb?</li>'
u' <li>!yyy?</li>'
u' </ul>'
u' </li>'
u'</ul>'
u'')

def test_without_amend_tag(self):
rendered = self._render(
u'{% load prepend append before after delete set_attributes from poleno.amend %}'
Expand Down

0 comments on commit c91e384

Please sign in to comment.