docs: def _scan_nodes(nodelist, context, instance_types, current_block=None, ignore_blocks=None):
      """
      Loop through all nodes of a single scope level.
  
      :type nodelist: django.template.base.NodeList
      :type current_block: BlockNode
      :param instance_types: The instance to look for
      """
      results = []
      for node in nodelist:
          # first check if this is the object instance to look for.
          if isinstance(node, instance_types):
              results.append(node)
              # if it's a Constant Include Node ({% include "template_name.html" %})
          # scan the child template
          elif isinstance(node, IncludeNode):
              # if there's an error in the to-be-included template, node.template becomes None
              if node.template:
                  # This is required for Django 1.7 but works on older version too
                  # Check if it quacks like a template object, if not
                  # presume is a template path and get the object out of it
                  if not callable(getattr(node.template, 'render', None)):
                      template = get_template(node.template.var)
                  else:
                      template = node.template
  
                  if TemplateAdapter is not None and isinstance(template, TemplateAdapter):
                      # Django 1.8: received a new object, take original template
                      template = template.template
  
                  results += _scan_nodes(template.nodelist, context, instance_types, current_block)
          # handle {% extends ... %} tags
          elif isinstance(node, ExtendsNode):
              results += _extend_nodelist(node, context, instance_types)
          # in block nodes we have to scan for super blocks
          elif isinstance(node, VariableNode) and current_block:
              if node.filter_expression.token == 'block.super':
                  # Found a {{ block.super }} line
                  if not hasattr(current_block.parent, 'nodelist'):
                      raise TemplateSyntaxError(
                          "Cannot read {{{{ block.super }}}} for {{% block {0} %}}, "
                          "the parent template doesn't have this block.".format(
                          current_block.name
                      ))
                  results += _scan_nodes(current_block.parent.nodelist, context, instance_types, current_block.parent)
          # ignore nested blocks which are already handled
          elif isinstance(node, BlockNode) and ignore_blocks and node.name in ignore_blocks:
              continue
          # if the node has the newly introduced 'child_nodelists' attribute, scan
          # those attributes for nodelists and recurse them
          elif hasattr(node, 'child_nodelists'):
              for nodelist_name in node.child_nodelists:
                  if hasattr(node, nodelist_name):
                      subnodelist = getattr(node, nodelist_name)
                      if isinstance(subnodelist, NodeList):
                          if isinstance(node, BlockNode):
                              current_block = node
                          results += _scan_nodes(subnodelist, context, instance_types, current_block)
          # else just scan the node for nodelist instance attributes
          else:
              for attr in dir(node):
                  obj = getattr(node, attr)
                  if isinstance(obj, NodeList):
                      if isinstance(node, BlockNode):
                          current_block = node
                      results += _scan_nodes(obj, context, instance_types, current_block)
      return results