<commit_before>module Chores
  class Chore
    attr_accessor :on_success, :on_failure, :on_stderr
    attr_accessor :command, :stdin, :stdout, :stderr
    attr_accessor :cost, :thread, :result
    attr_accessor :deps, :name, :completed

    def initialize(opts)
      [:on_success, :on_failure, :on_stderr].each do |cb|
        self.send :"#{cb}=", opts.fetch(cb).dup
      end

      self.name = opts[:name] || nil
      self.deps = opts[:deps] || []
      self.completed = Queue.new

      self.command = opts.fetch(:command).dup
      self.command = [self.command] unless self.command.is_a? Array
      self.cost    = opts[:cost] || nil
      self.stdin   = opts[:stdin] || nil
      self.stdout  = nil
      self.stderr  = Queue.new
      self.result  = :working
    end

    def satisfied?(completed)
      self.deps.empty? || self.deps.all?{|d| completed.include?(d)}
    end

    def run!
      self.thread = Thread.new do
        cmd = [self.command].flatten
        Open3.popen3(* cmd) do |i, o, e, t|
          i.write(self.stdin); i.close

          e.each_line do |line|
            self.stderr << line
          end
          e.close

          self.stdout = o.read
          o.close

          exit_status = t.value

          if exit_status.success?
            self.result = :success
          else
            self.result = :failure
          end
        end
      end
    end

    def complete?
      self.result == :success || self.result == :failure
    end

    def done_with(name)
      self.completed << name
    end

    def handle_completion
      if self.result == :success
        self.on_success.call
      elsif self.result == :failure
        self.on_failure.call
      else
        raise "This should not happen"
      end
    end

    def failed?
      self.result == :failure
    end<commit_msg>pass the chore out to the finishing callbacks, and give it a numeric exit status<commit_after>module Chores
  class Chore
    attr_accessor :on_success, :on_failure, :on_stderr, :exit_status
    attr_accessor :command, :stdin, :stdout, :stderr
    attr_accessor :cost, :thread, :result
    attr_accessor :deps, :name, :completed

    def initialize(opts)
      [:on_success, :on_failure, :on_stderr].each do |cb|
        self.send :"#{cb}=", opts.fetch(cb).dup
      end

      self.name = opts[:name] || nil
      self.deps = opts[:deps] || []
      self.completed = Queue.new

      self.command = opts.fetch(:command).dup
      self.command = [self.command] unless self.command.is_a? Array
      self.cost    = opts[:cost] || nil
      self.stdin   = opts[:stdin] || nil
      self.stdout  = nil
      self.stderr  = Queue.new
      self.result  = :working
    end

    def satisfied?(completed)
      self.deps.empty? || self.deps.all?{|d| completed.include?(d)}
    end

    def run!
      self.thread = Thread.new do
        cmd = [self.command].flatten
        Open3.popen3(* cmd) do |i, o, e, t|
          i.write(self.stdin); i.close

          e.each_line do |line|
            self.stderr << line
          end
          e.close

          self.stdout = o.read
          o.close

          result = t.value
          self.exit_status = result.exitstatus

          if result.success?
            self.result = :success
          else
            self.result = :failure
          end
        end
      end
    end

    def complete?
      self.result == :success || self.result == :failure
    end

    def done_with(name)
      self.completed << name
    end

    def handle_completion
      if self.result == :success
        self.on_success.call(self)
      elsif self.result == :failure
        self.on_failure.call(self)
      else
        raise "This should not happen"
      end
    end

    def failed?
      self.result == :failure
    end
{'fraction_non_alphanumeric': 0.1109350237717908, 'fraction_numerical': 0.0010565240359218173, 'mean_word_length': 1.8842345773038842, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, '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': '4968389', 'n_tokens_mistral': 1212, 'n_tokens_neox': 1177, 'n_words': 294}