def visit_For()

in ambari-common/src/main/python/ambari_jinja2/ambari_jinja2/compiler.py [0:0]


  def visit_For(self, node, frame):
    # when calculating the nodes for the inner frame we have to exclude
    # the iterator contents from it
    children = node.iter_child_nodes(exclude=("iter",))
    if node.recursive:
      loop_frame = self.function_scoping(node, frame, children, find_special=False)
    else:
      loop_frame = frame.inner()
      loop_frame.inspect(children)

    # try to figure out if we have an extended loop.  An extended loop
    # is necessary if the loop is in recursive mode if the special loop
    # variable is accessed in the body.
    extended_loop = node.recursive or "loop" in find_undeclared(
      node.iter_child_nodes(only=("body",)), ("loop",)
    )

    # if we don't have an recursive loop we have to find the shadowed
    # variables at that point.  Because loops can be nested but the loop
    # variable is a special one we have to enforce aliasing for it.
    if not node.recursive:
      aliases = self.push_scope(loop_frame, ("loop",))

    # otherwise we set up a buffer and add a function def
    else:
      self.writeline("def loop(reciter, loop_render_func):", node)
      self.indent()
      self.buffer(loop_frame)
      aliases = {}

    # make sure the loop variable is a special one and raise a template
    # assertion error if a loop tries to write to loop
    if extended_loop:
      loop_frame.identifiers.add_special("loop")
    for name in node.find_all(nodes.Name):
      if name.ctx == "store" and name.name == "loop":
        self.fail(
          "Can't assign to special loop variable " "in for-loop target", name.lineno
        )

    self.pull_locals(loop_frame)
    if node.else_:
      iteration_indicator = self.temporary_identifier()
      self.writeline(f"{iteration_indicator} = 1")

    # Create a fake parent loop if the else or test section of a
    # loop is accessing the special loop variable and no parent loop
    # exists.
    if "loop" not in aliases and "loop" in find_undeclared(
      node.iter_child_nodes(only=("else_", "test")), ("loop",)
    ):
      self.writeline(
        "l_loop = environment.undefined(%r, name='loop')"
        % (
          "'loop' is undefined. the filter section of a loop as well "
          "as the else block doesn't have access to the special 'loop'"
          " variable of the current loop.  Because there is no parent "
          "loop it's undefined.  Happened in loop on %s" % self.position(node)
        )
      )

    self.writeline("for ", node)
    self.visit(node.target, loop_frame)
    self.write(extended_loop and ", l_loop in LoopContext(" or " in ")

    # if we have an extened loop and a node test, we filter in the
    # "outer frame".
    if extended_loop and node.test is not None:
      self.write("(")
      self.visit(node.target, loop_frame)
      self.write(" for ")
      self.visit(node.target, loop_frame)
      self.write(" in ")
      if node.recursive:
        self.write("reciter")
      else:
        self.visit(node.iter, loop_frame)
      self.write(" if (")
      test_frame = loop_frame.copy()
      self.visit(node.test, test_frame)
      self.write("))")

    elif node.recursive:
      self.write("reciter")
    else:
      self.visit(node.iter, loop_frame)

    if node.recursive:
      self.write(", recurse=loop_render_func):")
    else:
      self.write(extended_loop and "):" or ":")

    # tests in not extended loops become a continue
    if not extended_loop and node.test is not None:
      self.indent()
      self.writeline("if not ")
      self.visit(node.test, loop_frame)
      self.write(":")
      self.indent()
      self.writeline("continue")
      self.outdent(2)

    self.indent()
    self.blockvisit(node.body, loop_frame)
    if node.else_:
      self.writeline(f"{iteration_indicator} = 0")
    self.outdent()

    if node.else_:
      self.writeline(f"if {iteration_indicator}:")
      self.indent()
      self.blockvisit(node.else_, loop_frame)
      self.outdent()

    # reset the aliases if there are any.
    if not node.recursive:
      self.pop_scope(aliases, loop_frame)

    # if the node was recursive we have to return the buffer contents
    # and start the iteration code
    if node.recursive:
      self.return_buffer_contents(loop_frame)
      self.outdent()
      self.start_write(frame, node)
      self.write("loop(")
      self.visit(node.iter, frame)
      self.write(", loop)")
      self.end_write(frame)