code: def foreach_loop(self, context):
          
          logger.debug("starting")
  
          # Loop decorators only evaluated once, not for every step repeat
          # execution.
          foreach = context.get_formatted_iterable(self.foreach_items)
  
          foreach_length = len(foreach)
  
          logger.info(f"foreach decorator will loop {foreach_length} times.")
  
          for i in foreach:
              logger.info(f"foreach: running step {i}")
              # the iterator must be available to the step when it executes
              context['i'] = i
              # conditional operators apply to each iteration, so might be an
              # iteration run, skips or swallows.
              self.run_conditional_decorators(context)
              logger.debug(f"foreach: done step {i}")
  
          logger.debug(f"foreach decorator looped {foreach_length} times.")
          logger.debug("done")
docs: Run step once for each item in foreach_items.
  
          On each iteration, the invoked step can use context['i'] to get the
          current iterator value.
  
          Args:
              context: (pypyr.context.Context) The pypyr context. This arg will
                       mutate.