def test_inclusion_tag_push_pop_context(self): class IncPollute(helpers.InclusionTag): template = 'test.html' options = core.Options(arguments.Argument('var')) def get_context(self, context, var): context.update({'var': 'polluted'}) return context with TemplateTags(IncPollute): tpl = template.Template('{% inc_pollute var %}') ctx = template.Context({'var': 'test'}) out = tpl.render(ctx) self.assertEqual(out, 'polluted') self.assertEqual(ctx['var'], 'polluted') # now enable pollution control IncPollute.push_context = True with TemplateTags(IncPollute): tpl = template.Template('{% inc_pollute var %}') ctx = template.Context({'var': 'test'}) out = tpl.render(ctx) self.assertEqual(out, 'polluted') self.assertEqual(ctx['var'], 'test')
def test_07_cycle(self): """ This test re-implements django's cycle tag (because it's quite crazy) and checks if it works. """ from itertools import cycle as itertools_cycle class Cycle(core.Tag): name = 'classy_cycle' options = core.Options( arguments.MultiValueArgument('values'), 'as', arguments.Argument('varname', required=False, resolve=False), ) def render_tag(self, context, values, varname): if self not in context.render_context: context.render_context[self] = itertools_cycle(values) cycle_iter = context.render_context[self] value = cycle_iter.next() if varname: context[varname] = value return value origtpl = template.Template( '{% for thing in sequence %}' '{% cycle "1" "2" "3" "4" %}' '{% endfor %}' ) sequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] context = template.Context({'sequence': sequence}) original = origtpl.render(context) with TemplateTags(Cycle): classytpl = template.Template( '{% for thing in sequence %}' '{% classy_cycle "1" "2" "3" "4" %}' '{% endfor %}' ) classy = classytpl.render(context) self.assertEqual(original, classy) origtpl = template.Template( '{% for thing in sequence %}' '{% cycle "1" "2" "3" "4" as myvarname %}' '{% endfor %}' ) sequence = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] context = template.Context({'sequence': sequence}) original = origtpl.render(context) with TemplateTags(Cycle): classytpl = template.Template( '{% for thing in sequence %}' '{% classy_cycle "1" "2" "3" "4" as myvarname %}' '{% endfor %}' ) classy = classytpl.render(context) self.assertEqual(original, classy)
def test_29_named_block_noresolve(self): class StartBlock(core.Tag): options = core.Options( arguments.Argument("myarg", resolve=False), blocks=[ BlockDefinition("nodelist", VariableBlockName("end_block %(value)s", 'myarg'), "end_block") ] ) def render_tag(self, context, myarg, nodelist): return "nodelist:%s;myarg:%s" % (nodelist.render(context), myarg) with TemplateTags(StartBlock): ctx = template.Context() tpl = template.Template( "{% start_block 'hello' %}nodelist-content" "{% end_block 'hello' %}" ) output = tpl.render(ctx) expected_output = 'nodelist:nodelist-content;myarg:hello' self.assertEqual(output, expected_output)
def test_26_inclusion_tag_context_pollution(self): """ Check the `keep_render_context` and `push_pop_context` attributes on InclusionTag work as advertised and prevent 'context pollution' """ class NoPushPop(helpers.InclusionTag): template = 'inclusion.html' def get_context(self, context): return context.update({'pollution': True}) class Standard(helpers.InclusionTag): template = 'inclusion.html' def get_context(self, context): return {'pollution': True} with TemplateTags(NoPushPop, Standard): # push pop pollution ctx1 = template.Context({'pollution': False}) tpl1 = template.Template("{% no_push_pop %}") tpl1.render(ctx1) self.assertEqual(ctx1['pollution'], True) ctx2 = template.Context({'pollution': False}) tpl2 = template.Template("{% standard %}") tpl2.render(ctx2) self.assertEqual(ctx2['pollution'], False)
def _tag_tester(self, klass, templates): """ Helper method to test a template tag by rendering it and checkout output. *klass* is a template tag class (subclass of core.Tag) *templates* is a sequence of a triple (template-string, output-string, context) """ TAG_MESSAGE = ("Rendering of template %(in)r resulted in " "%(realout)r, expected %(out)r using %(ctx)r.") with TemplateTags(klass): for tpl, out, ctx in templates: t = template.Template(tpl) c = template.Context(ctx) s = t.render(c) self.assertEqual(s, out, TAG_MESSAGE % { 'in': tpl, 'out': out, 'ctx': ctx, 'realout': s, }) for key, value in ctx.items(): self.assertEqual(c.get(key), value)
def test_15_not_implemented_errors(self): class Fail(core.Tag): pass class Fail2(helpers.AsTag): pass class Fail3(helpers.AsTag): options = core.Options( 'as', ) class Fail4(helpers.AsTag): options = core.Options( 'as', arguments.Argument('varname', resolve=False), ) class Fail5(helpers.InclusionTag): pass with TemplateTags(Fail, Fail2, Fail3, Fail4, Fail5): context = template.Context({}) tpl = template.Template("{% fail %}") self.assertRaises(NotImplementedError, tpl.render, context) self.assertRaises(ImproperlyConfigured, template.Template, "{% fail2 %}") self.assertRaises(ImproperlyConfigured, template.Template, "{% fail3 %}") tpl = template.Template("{% fail4 as something %}") self.assertRaises(NotImplementedError, tpl.render, context) self.assertRaises(ImproperlyConfigured, template.Template, "{% fail5 %}")
def test_too_many_arguments(self): class NoArg(core.Tag): pass with TemplateTags(NoArg): self.assertRaises(exceptions.TooManyArguments, template.Template, "{% no_arg a arg %}")
def test_not_implemented_errors(self): class Fail(core.Tag): pass class Fail2(helpers.AsTag): pass class Fail3(helpers.AsTag): options = core.Options('as', ) class Fail4(helpers.AsTag): options = core.Options( 'as', arguments.Argument('varname', resolve=False), ) if DJANGO_1_4_OR_HIGHER: exc_class = NotImplementedError else: # pragma: no cover exc_class = template.TemplateSyntaxError with TemplateTags(Fail, Fail2, Fail3, Fail4): context = template.Context({}) tpl = template.Template("{% fail %}") self.assertRaises(exc_class, tpl.render, context) self.assertRaises(ImproperlyConfigured, template.Template, "{% fail2 %}") self.assertRaises(ImproperlyConfigured, template.Template, "{% fail3 %}") tpl = template.Template("{% fail4 as something %}") self.assertRaises(exc_class, tpl.render, context)
def test_integer_variable(self): options = core.Options( arguments.IntegerArgument('integer', resolve=False), ) # test okay with SettingsOverride(DEBUG=False): dummy_tokens = DummyTokens('1') kwargs, blocks = options.parse(dummy_parser, dummy_tokens) dummy_context = {} self.assertEqual(kwargs['integer'].resolve(dummy_context), 1) # test warning dummy_tokens = DummyTokens('one') kwargs, blocks = options.parse(dummy_parser, dummy_tokens) dummy_context = {} one = repr('one') message = arguments.IntegerValue.errors['clean'] % {'value': one} self.assertWarns(exceptions.TemplateSyntaxWarning, message, kwargs['integer'].resolve, dummy_context) self.assertEqual(kwargs['integer'].resolve(dummy_context), values.IntegerValue.value_on_error) # test exception with SettingsOverride(DEBUG=True): dummy_tokens = DummyTokens('one') kwargs, blocks = options.parse(dummy_parser, dummy_tokens) dummy_context = {} message = values.IntegerValue.errors['clean'] % { 'value': repr('one') } self.assertRaises(template.TemplateSyntaxError, kwargs['integer'].resolve, dummy_context) # test the same as above but with resolving class IntegerTag(core.Tag): options = core.Options(arguments.IntegerArgument('integer')) def render_tag(self, context, integer): return integer with TemplateTags(IntegerTag): tpl = template.Template("{% integer_tag i %}") with SettingsOverride(DEBUG=False): # test okay context = template.Context({'i': '1'}) self.assertEqual(tpl.render(context), '1') # test warning context = template.Context({'i': 'one'}) message = values.IntegerValue.errors['clean'] % { 'value': repr('one') } self.assertWarns(exceptions.TemplateSyntaxWarning, message, tpl.render, context) self.assertEqual(int(tpl.render(context)), values.IntegerValue.value_on_error) # test exception with SettingsOverride(DEBUG=True): context = template.Context({'i': 'one'}) message = arguments.IntegerValue.errors['clean'] % {'value': one} self.assertRaises(template.TemplateSyntaxError, tpl.render, context)