#23441: Maximum recursion depth exceeded when using custom `inclusion_tag` with
recursion in templates and `django.template.loaders.cached.Loader`
-------------------------------+--------------------
     Reporter:  vstoykov       |      Owner:  nobody
         Type:  Bug            |     Status:  new
    Component:  Uncategorized  |    Version:  1.7
     Severity:  Normal         |   Keywords:
 Triage Stage:  Unreviewed     |  Has patch:  1
Easy pickings:  0              |      UI/UX:  0
-------------------------------+--------------------
 When custom `inclusion_tag` is created which use recursion in the template
 (call itself) and also template loader used is
 `django.template.loaders.cached.Loader`. In this situation when template
 containing this inclusion tag is rendered for the second time (then the
 template is fetched from the cache) then `maximum recursion depth
 exceeded` error is raised.

 The reason for this is when `{% extends %}` template tag start to look for
 `{% block %}` tags it calls `Node.get_nodes_by_type` which start looking
 for `{% block %}` tags in the template. When reach our custom inclusion
 tag node and call it's `get_nodes_by_type` method to look for `{% block
 %}` then start iteration over cached nodes from included template. This
 will not happen when standard template loaders are used because template
 for inclusion tag is not parsed yet.

 To reproduce the error you can use github repo created for that purpose
 (https://github.com/vstoykov/wpadmin-test)

 I think that there is two possible approaches to fix this, both of which
 prevent iteration over cached nodes.

 1. Set `child_nodelists` attribute of `InclusionNode` to be empty iterable
 (tuple for example).
 2. Change the name of the attribute in which the cached nodes are stored
 from `nodelist` to something else.

 For me the first variant is preferred because we explicitly tell that this
 node doesn't have any child nodes.

 I created a patch with first variant. If you are ok with it I can make
 pull request on github if necessary.

 Attached Traceback:
 {{{
 Environment:

 Request Method: GET
 Request URL: http://localhost:8000/admin/

 Django Version: 1.7
 Python Version: 2.7.6
 Installed Applications:
 ('wpadmin',
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
  'django.contrib.redirects',
  'django.contrib.sites')
 Installed Middleware:
 ('django.contrib.sessions.middleware.SessionMiddleware',
  'django.middleware.common.CommonMiddleware',
  'django.middleware.csrf.CsrfViewMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
  'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
  'django.contrib.messages.middleware.MessageMiddleware',
  'django.middleware.clickjacking.XFrameOptionsMiddleware')


 Template error:
 In template /home/venko/.pyvirtualenvs/django-max-
 recursion/local/lib/python2.7/site-
 packages/wpadmin/templates/admin/base_site.html, error at line 1
    maximum recursion depth exceeded
    1 :  {% extends "admin/base.html" %}
    2 : {% load i18n wpadmin_tags %}
    3 :
    4 : {% block title %}{{ title }} | {% wpadmin_render_custom_title %}{%
 endblock %}
    5 :
    6 : {% block branding %}
    7 : <h1 id="site-name">{% trans 'Django administration' %}</h1>
    8 : {% endblock %}
    9 :
    10 : {% block nav-global %}{% endblock %}
    11 :

 Traceback:
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/core/handlers/base.py" in get_response
   137.                 response = response.render()
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/response.py" in render
   103.             self.content = self.rendered_content
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/response.py" in rendered_content
   80.         content = template.render(context)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in render
   148.             return self._render(context)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in _render
   142.         return self.nodelist.render(context)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in render
   844.                 bit = self.render_node(node, context)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/debug.py" in render_node
   80.             return node.render(context)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/loader_tags.py" in render
   126.         return compiled_parent._render(context)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in _render
   142.         return self.nodelist.render(context)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in render
   844.                 bit = self.render_node(node, context)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/debug.py" in render_node
   80.             return node.render(context)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/loader_tags.py" in render
   120.
 compiled_parent.nodelist.get_nodes_by_type(BlockNode))
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   854.             nodes.extend(node.get_nodes_by_type(nodetype))
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   831.                 nodes.extend(nodelist.get_nodes_by_type(nodetype))
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   854.             nodes.extend(node.get_nodes_by_type(nodetype))
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   831.                 nodes.extend(nodelist.get_nodes_by_type(nodetype))
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   854.             nodes.extend(node.get_nodes_by_type(nodetype))
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   831.                 nodes.extend(nodelist.get_nodes_by_type(nodetype))
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   854.             nodes.extend(node.get_nodes_by_type(nodetype))

 ............................

 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   831.                 nodes.extend(nodelist.get_nodes_by_type(nodetype))
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   854.             nodes.extend(node.get_nodes_by_type(nodetype))
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/base.py" in get_nodes_by_type
   829.             nodelist = getattr(self, attr, None)
 File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7
 /site-packages/django/template/defaulttags.py" in nodelist
   298.         return NodeList(node for _, nodelist in
 self.conditions_nodelists for node in nodelist)

 Exception Type: RuntimeError at /admin/
 Exception Value: maximum recursion depth exceeded

 }}}

--
Ticket URL: <https://code.djangoproject.com/ticket/23441>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/051.fa696ed65d2d1a6775a22d6ab92ac1ac%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to