<commit_before>module AttrVault
  class InvalidKey < StandardError; end
  class InvalidKeyring < StandardError; end

  class Key
    attr_reader :id, :value, :created_at

    def initialize(id, value, created_at=Time.now)
      if id.nil?
        raise InvalidKey, "key id required"
      end
      if value.nil?
        raise InvalidKey, "key value required"
      end

      @id = id
      @value = value
      @created_at = if created_at.is_a? String
                      Time.parse(created_at)
                    else
                      created_at
                    end
    end

    def to_json
      { id: id, value: value, created_at: created_at }
    end
  end

  class Keyring
    attr_reader :keys

    def self.load(keyring_data)
      keyring = Keyring.new
      begin
        candidate_keys = JSON.parse(keyring_data)
        unless candidate_keys.respond_to? :each_with_index
          raise InvalidKeyring, "does not respond to each_with_index"
        end
        candidate_keys.each_with_index do |k, i|
          keyring.add_key(Key.new(k["id"], k["value"], k["created_at"]))
        end
      rescue StandardError => e
        raise InvalidKeyring, e.message
      end
      keyring
    end

    def initialize
      @keys = []
    end

    def add_key(k)
      @keys << k
    end

    def drop_key(id_or_key)
      id = if id_or_key.is_a? Key
             id_or_key.id
           else
             id_or_key
           end
      @keys.reject! { |k| k.id == id }
    end<commit_msg>More sensible division of responsibilities for key parsing<commit_after>module AttrVault
  class InvalidKey < StandardError; end
  class InvalidKeyring < StandardError; end

  class Key
    attr_reader :id, :value, :created_at

    def initialize(id, value, created_at)
      if id.nil?
        raise InvalidKey, "key id required"
      end
      if value.nil?
        raise InvalidKey, "key value required"
      end

      @id = id
      @value = value
      @created_at = created_at
    end

    def to_json
      { id: id, value: value, created_at: created_at }.to_json
    end
  end

  class Keyring
    attr_reader :keys

    def self.load(keyring_data)
      keyring = Keyring.new
      begin
        candidate_keys = JSON.parse(keyring_data)
        unless candidate_keys.respond_to? :each_with_index
          raise InvalidKeyring, "does not respond to each_with_index"
        end
        candidate_keys.each_with_index do |k, i|
          created_at = unless k["created_at"].nil?
                         Time.parse(k["created_at"])
                       end
          keyring.add_key(Key.new(k["id"], k["value"], created_at || Time.now))
        end
      rescue StandardError => e
        raise InvalidKeyring, e.message
      end
      keyring
    end

    def initialize
      @keys = []
    end

    def add_key(k)
      @keys << k
    end

    def drop_key(id_or_key)
      id = if id_or_key.is_a? Key
             id_or_key.id
           else
             id_or_key
           end
      @keys.reject! { |k| k.id == id }
    end
{'fraction_non_alphanumeric': 0.07762856207009498, 'fraction_numerical': 0.0, 'mean_word_length': 1.8251618871415356, 'pattern_counts': {'":': 0, '<': 11, '<?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': '1846779', 'n_tokens_mistral': 961, 'n_tokens_neox': 940, 'n_words': 251}