<commit_before>module NextStep
  module StepRunner

    # Pass a list of steps which are an array of callable objects (lambda, proc, etc)

    def run_steps(steps, errors=[])
      @step_errors = errors
      result = steps.each { |step|  break false unless process_result(execute_step(step), step) }
      result && @step_errors.empty?
    end

    # a container for any errors encountered while running steps. 
    # Adding items to the container will result in the run_steps method
    # returning false indicating a failed attempt at running all the 
    # steps successfully
    def step_errors
      @step_errors ||= []
    end

    def step_results 
      @step_results ||= []
    end

    def safely(description)
      yield if block_given?
      proceed
    rescue => e
      stop_with_exception description, e
    end

    # Can be overridden to allow wrapping functionality around 
    # running a step or calling steps in different ways.
    # See NextStep::EventProcessor for an example
    def execute_step(step)
      result = case 
      when step.respond_to?(:call) then step.call
      when step.kind_of?(Symbol) then send(step)
      else
        fail "Invalid step. Must be a callable object or symbol method reference."
      end
      result
    end

    def process_result(result, step)
      result.step = step.to_s
      advances.each do |callable|
        callable.call(result)
      end
      step_results << result
      result.continue
    end

    # Use this to send the step runner a halt and don't process anything else.
    def halt
      StepResult.new(false)
    end

    # Use stop to add an error and completely stop the steps from proceeding.
    def stop(message="")
      step_errors << message unless message.nil? || message.empty?
      StepResult.new(false, message)
    end

    # Use invalid to add an error but continue procesing other steps.
    # Eventual result will be false. This is good for a set of validations 
    # where you want to collect all the errors.
    def invalid(message)
      step_errors << message
      StepResult.new(true, message)
    end

    def proceed
      StepResult.new(true)
    end

    # Allow a block to be called after each step is run
    def on_advance(&block)
      advances << block
    end

    def advances
      @advances ||= []
    end

    def stop_with_exception(description, exception)
      StepResult.new(false, "Exception when #{description}", exception)
    end

  end
end<commit_msg>Add exception messages to step_errors when catching exceptions<commit_after>module NextStep
  module StepRunner

    # Pass a list of steps which are an array of callable objects (lambda, proc, etc)

    def run_steps(steps, errors=[])
      @step_errors = errors
      result = steps.each { |step|  break false unless process_result(execute_step(step), step) }
      result && @step_errors.empty?
    end

    # a container for any errors encountered while running steps. 
    # Adding items to the container will result in the run_steps method
    # returning false indicating a failed attempt at running all the 
    # steps successfully
    def step_errors
      @step_errors ||= []
    end

    def step_results 
      @step_results ||= []
    end

    def safely(description)
      yield if block_given?
      proceed
    rescue => e
      stop_with_exception description, e
    end

    # Can be overridden to allow wrapping functionality around 
    # running a step or calling steps in different ways.
    # See NextStep::EventProcessor for an example
    def execute_step(step)
      result = case 
      when step.respond_to?(:call) then step.call
      when step.kind_of?(Symbol) then send(step)
      else
        fail "Invalid step. Must be a callable object or symbol method reference."
      end
      result
    end

    def process_result(result, step)
      result.step = step.to_s
      advances.each do |callable|
        callable.call(result)
      end
      step_results << result
      result.continue
    end

    # Use this to send the step runner a halt and don't process anything else.
    def halt
      StepResult.new(false)
    end

    # Use stop to add an error and completely stop the steps from proceeding.
    def stop(message="")
      step_errors << message unless message.nil? || message.empty?
      StepResult.new(false, message)
    end

    # Use invalid to add an error but continue procesing other steps.
    # Eventual result will be false. This is good for a set of validations 
    # where you want to collect all the errors.
    def invalid(message)
      step_errors << message
      StepResult.new(true, message)
    end

    def proceed
      StepResult.new(true)
    end

    # Allow a block to be called after each step is run
    def on_advance(&block)
      advances << block
    end

    def advances
      @advances ||= []
    end

    def stop_with_exception(description, exception)
      message = "Exception when #{description}"
      step_errors << message
      StepResult.new(false, message, exception)
    end

  end
end
{'fraction_non_alphanumeric': 0.06452249408050513, 'fraction_numerical': 0.0, 'mean_word_length': 2.5646976090014064, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1435915', 'n_tokens_mistral': 1395, 'n_tokens_neox': 1350, 'n_words': 542}