<commit_before>require 'monkeypatches/io'

class TrackSensor::Base
  def initialize(options = {})
    @device_glob = ENV['TRACK_SENSOR_DEVICE'] || options[:device_glob] || '/dev/tty{USB,.usbserial}*'
    @devices = []
    @data = {}
    initialize_new_devices
  end

  def race_results
    raise NotImplementedError
  end

  def new_race
    raise NotImplementedError
  end

  def close
    @devices.each &:close
    @devices.clear
  end

protected

  # Communicate with the serial device.
  # Try to communicate with all device files that match the device_glob option to {#initialize}.
  # IO errors that occur while reading or writing to a device cause the device to be temporarily
  # ignored until the next call to this method.
  # The block should do only non-blocking IO using read_nonblock and write_nonblock.
  # The block need not handle exceptions raised caused by when IO would block.
  # @yield [device] IO object to read from and write to
  # @raise [IOError] if no device is available for use
  def communicate
    scan_for_device_changes do |failed_devices|
      @devices.each do |device|
        begin
          yield device
        rescue IO::WaitWritable, IO::WaitReadable
        rescue IOError, Errno::ENXIO
          failed_devices << device
        end
      end
    end
  end

private

  def initialize_device(device_path)
    return false unless File.writable? device_path
    device = SerialPort.new device_path, serial_params.stringify_keys.reverse_merge('baud' => 9600, 'data_bits' => 8, 'stop_bits' => 1, 'parity' => SerialPort::NONE)<commit_msg>Add a couple more IO related device failure exceptions<commit_after>require 'monkeypatches/io'

class TrackSensor::Base
  def initialize(options = {})
    @device_glob = ENV['TRACK_SENSOR_DEVICE'] || options[:device_glob] || '/dev/tty{USB,.usbserial}*'
    @devices = []
    @data = {}
    initialize_new_devices
  end

  def race_results
    raise NotImplementedError
  end

  def new_race
    raise NotImplementedError
  end

  def close
    @devices.each &:close
    @devices.clear
  end

protected

  # Communicate with the serial device.
  # Try to communicate with all device files that match the device_glob option to {#initialize}.
  # IO errors that occur while reading or writing to a device cause the device to be temporarily
  # ignored until the next call to this method.
  # The block should do only non-blocking IO using read_nonblock and write_nonblock.
  # The block need not handle exceptions raised caused by when IO would block.
  # @yield [device] IO object to read from and write to
  # @raise [IOError] if no device is available for use
  def communicate
    scan_for_device_changes do |failed_devices|
      @devices.each do |device|
        begin
          yield device
        rescue IO::WaitWritable, IO::WaitReadable
        rescue IOError, Errno::ENXIO, Errno::EIO, Errno::EBUSY
          failed_devices << device
        end
      end
    end
  end

private

  def initialize_device(device_path)
    return false unless File.writable? device_path
    device = SerialPort.new device_path, serial_params.stringify_keys.reverse_merge('baud' => 9600, 'data_bits' => 8, 'stop_bits' => 1, 'parity' => SerialPort::NONE)
{'fraction_non_alphanumeric': 0.07646875971401927, 'fraction_numerical': 0.003730183400683867, 'mean_word_length': 3.4386206896551723, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, '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': '1517869', 'n_tokens_mistral': 952, 'n_tokens_neox': 929, 'n_words': 329}