<commit_before>module TrustedSandbox
  class Response

    attr_reader :host_code_dir_path, :output_file_name, :stdout, :stderr,
                :raw_response, :status, :error, :error_to_raise, :output

    # @param stdout [String, Array] response of stdout from the container
    # @param stderr [String, Array] response of stderr from the container
    # @param host_code_dir_path [String] path to the folder where the argument value needs to be stored
    # @param output_file_name [String] name of output file inside the host_code_dir_path
    def initialize(stdout = nil, stderr = nil, host_code_dir_path = nil, output_file_name = nil)
      @stdout = stdout
      @stderr = stderr
      @host_code_dir_path = host_code_dir_path
      @output_file_name = output_file_name
    end

    # @return [Response] object initialized with timeout error details
    def self.timeout_error(err, logs)
      obj = new(logs)
      obj.instance_eval do
        @status = 'error'
        @error = err
        @error_to_raise = TrustedSandbox::ExecutionTimeoutError.new(err)
      end
      obj
    end

    # @return [Boolean]
    def valid?
      status == 'success'
    end

    # @return [Object] the output returned by the container. Raises errors if encountered.
    # @raise [ContainerError, UserCodeError, InternalError] if errors were raised by the container, they are bubbled
    #   as UserCodeError
    def output!
      propagate_errors!
      output
    end

    # Parses the output file and stores the values in the appropriate ivars
    # @return [nil]
    def parse!
      begin
        data = File.binread output_file_path
        @raw_response = Marshal.load(data)
      rescue => e
        @status = 'error'
        @error = e
        @error_to_raise = ContainerError.new(e)
        return
      end

      unless ['success', 'error'].include? @raw_response[:status]
        @status = 'error'
        @error = ContainerError.new('Output file has invalid format')
        @error_to_raise = @error
        return
      end

      @status = @raw_response[:status]
      @output = @raw_response[:output]
      @error = @raw_response[:error]
      @error_to_raise = UserCodeError.new(@error) if @error
      nil
    end

    private

    def output_file_path
      File.join(host_code_dir_path, output_file_name)
    end

    def propagate_errors!
      return if valid?
      raise InternalError.new 'Response object is invalid but no errors were recorded.' unless error
      raise error_to_raise
    end

  end
end<commit_msg>Added error handler for when output file is not found<commit_after>module TrustedSandbox
  class Response

    attr_reader :host_code_dir_path, :output_file_name, :stdout, :stderr,
                :raw_response, :status, :error, :error_to_raise, :output

    # @param stdout [String, Array] response of stdout from the container
    # @param stderr [String, Array] response of stderr from the container
    # @param host_code_dir_path [String] path to the folder where the argument value needs to be stored
    # @param output_file_name [String] name of output file inside the host_code_dir_path
    def initialize(stdout = nil, stderr = nil, host_code_dir_path = nil, output_file_name = nil)
      @stdout = stdout
      @stderr = stderr
      @host_code_dir_path = host_code_dir_path
      @output_file_name = output_file_name
    end

    # @return [Response] object initialized with timeout error details
    def self.timeout_error(err, logs)
      obj = new(logs)
      obj.instance_eval do
        @status = 'error'
        @error = err
        @error_to_raise = TrustedSandbox::ExecutionTimeoutError.new(err)
      end
      obj
    end

    # @return [Boolean]
    def valid?
      status == 'success'
    end

    # @return [Object] the output returned by the container. Raises errors if encountered.
    # @raise [ContainerError, UserCodeError, InternalError] if errors were raised by the container, they are bubbled
    #   as UserCodeError
    def output!
      propagate_errors!
      output
    end

    # Parses the output file and stores the values in the appropriate ivars
    # @return [nil]
    def parse!
      unless File.exists? output_file_path
        @status = 'error'
        @error = ContainerError.new('User code did not finish properly')
        @error_to_raise = @error
        return
      end

      begin
        data = File.binread output_file_path
        @raw_response = Marshal.load(data)
      rescue => e
        @status = 'error'
        @error = e
        @error_to_raise = ContainerError.new(e)
        return
      end

      unless ['success', 'error'].include? @raw_response[:status]
        @status = 'error'
        @error = InternalError.new('Output file has invalid format')
        @error_to_raise = @error
        return
      end

      @status = @raw_response[:status]
      @output = @raw_response[:output]
      @error = @raw_response[:error]
      @error_to_raise = UserCodeError.new(@error) if @error
      nil
    end

    private

    def output_file_path
      File.join(host_code_dir_path, output_file_name)
    end

    def propagate_errors!
      return if valid?
      raise InternalError.new 'Response object is invalid but no errors were recorded.' unless error
      raise error_to_raise
    end

  end
end
{'fraction_non_alphanumeric': 0.07576328684508105, 'fraction_numerical': 0.0, 'mean_word_length': 2.716386554621849, 'pattern_counts': {'":': 0, '<': 3, '<?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': '6791882', 'n_tokens_mistral': 1553, 'n_tokens_neox': 1521, 'n_words': 484}