<commit_before>require 'duse/client/entity'
require 'faraday'
require 'faraday_middleware'

module Duse
  module Client
    class Error < StandardError; end
    class SSLError < Error; end
    class NotLoggedIn < Error; end
    class NotAuthorized < Error; end
    class NotFound < Error; end
    class ValidationFailed < Error; end

    class Session
      attr_accessor :token, :uri

      def find_one(entity, id)
        response_body = get("/#{entity.base_path}/#{id}")
        instance_from(entity, response_body)
      end

      def find_many(entity, params = {})
        response_body = get("/#{entity.base_path}")
        instances_from(entity, response_body)
      end

      def create(entity, hash)
        response_body = post("/#{entity.base_path}", hash)
        instance_from(entity, response_body)
      end

      def update(entity, id, hash)
        response_body = patch("/#{entity.base_path}/#{id}", hash)
        instance_from(entity, response_body)
      end

      def delete_one(entity, id)
        delete("/#{entity.base_path}/#{id}")
      end

      def get(*args)
        raw(:get, *args)
      end

      def post(*args)
        raw(:post, *args)
      end

      def patch(*args)
        raw(:patch, *args)
      end

      def delete(*args)
        raw(:delete, *args)
      end

      def raw(verb, url, *args)
        fail ArgumentError, 'Uri must be set' if uri.nil?

        result = connection.public_send(verb, url, *args) do |request|
          request.headers['Authorization'] = token unless token.nil?
          request.headers['Accept'] = 'application/vnd.duse.1+json'
        end

        case result.status
        when 0             then raise SSLError, 'SSL error: could not verify peer'
        when 200..299      then JSON.parse(result.body) rescue result.body
        when 301, 303      then raw(:get, result.headers['Location'])
        when 302, 307, 308 then raw(verb, result.headers['Location'])
        when 401           then raise NotLoggedIn,      error_msg(result.body)
        when 403           then raise NotAuthorized,    error_msg(result.body)
        when 404           then raise NotFound,         error_msg(result.body)
        when 422           then raise ValidationFailed, error_msg(result.body)
        when 400..499      then raise Error,            error_msg(result.body)
        when 500..599      then raise Error,            error_msg(result.body)
        else raise Error, "unhandled status code #{result.status}"
        end
      end

      def error_msg(json)
        result = JSON.parse(json)['message']
        result = result.join "\n" if result.is_a? Array
        result
      rescue
        json
      end

      def connection
        @connection ||= Faraday.new url: uri do |faraday|
          faraday.request  :json
          faraday.response :json, content_type: /\bjson$/
          faraday.adapter  *faraday_adapter
        end
      end

      def faraday_adapter
        Faraday.default_adapter
      end

      private

      def instances_from(entity, array)
        array.map { |e| instance_from(entity, e) }
      end

      def instance_from(entity, hash)
        instance = entity.new
        entity.attributes.each do |attribute|
          if hash.has_key? attribute
            value = hash[attribute]
            if Entity::MAP.has_key? attribute
              nested_entity = Entity::MAP[attribute]
              value = hash[attribute].map { |e| instance_from(nested_entity, e) }
            end
            instance.public_send("#{attribute}=", value)
          end
        end
        instance
      end
    end
  end
end
<commit_msg>split http request and request processing<commit_after>require 'duse/client/entity'
require 'faraday'
require 'faraday_middleware'

module Duse
  module Client
    class Error < StandardError; end
    class SSLError < Error; end
    class NotLoggedIn < Error; end
    class NotAuthorized < Error; end
    class NotFound < Error; end
    class ValidationFailed < Error; end

    class Session
      attr_accessor :token, :uri

      def find_one(entity, id)
        response_body = get("/#{entity.base_path}/#{id}")
        instance_from(entity, response_body)
      end

      def find_many(entity, params = {})
        response_body = get("/#{entity.base_path}")
        instances_from(entity, response_body)
      end

      def create(entity, hash)
        response_body = post("/#{entity.base_path}", hash)
        instance_from(entity, response_body)
      end

      def update(entity, id, hash)
        response_body = patch("/#{entity.base_path}/#{id}", hash)
        instance_from(entity, response_body)
      end

      def delete_one(entity, id)
        delete("/#{entity.base_path}/#{id}")
      end

      def get(*args)
        raw(:get, *args)
      end

      def post(*args)
        raw(:post, *args)
      end

      def patch(*args)
        raw(:patch, *args)
      end

      def delete(*args)
        raw(:delete, *args)
      end

      def raw(*args)
        process_raw_http_response raw_http_request(*args)
      end

      def process_raw_http_response(response)
        case response.status
        when 0             then raise SSLError, 'SSL error: could not verify peer'
        when 200..299      then JSON.parse(response.body) rescue response.body
        when 301, 303      then raw(:get, response.headers['Location'])
        when 302, 307, 308 then raw(verb, response.headers['Location'])
        when 401           then raise NotLoggedIn,      error_msg(response.body)
        when 403           then raise NotAuthorized,    error_msg(response.body)
        when 404           then raise NotFound,         error_msg(response.body)
        when 422           then raise ValidationFailed, error_msg(response.body)
        when 400..499      then raise Error,            error_msg(response.body)
        when 500..599      then raise Error,            error_msg(response.body)
        else raise Error, "unhandled status code #{response.status}"
        end
      end

      def raw_http_request(*args)
        connection.public_send(*args) do |request|
          request.headers['Authorization'] = token unless token.nil?
          request.headers['Accept'] = 'application/vnd.duse.1+json'
        end
      end

      def error_msg(json)
        result = JSON.parse(json)['message']
        result = result.join "\n" if result.is_a? Array
        result
      rescue
        json
      end

      def connection
        fail ArgumentError, 'Uri must be set' if uri.nil?

        @connection ||= Faraday.new url: uri do |faraday|
          faraday.request  :json
          faraday.response :json, content_type: /\bjson$/
          faraday.adapter  *faraday_adapter
        end
      end

      def faraday_adapter
        Faraday.default_adapter
      end

      private

      def instances_from(entity, array)
        array.map { |e| instance_from(entity, e) }
      end

      def instance_from(entity, hash)
        instance = entity.new
        entity.attributes.each do |attribute|
          if hash.has_key? attribute
            value = hash[attribute]
            if Entity::MAP.has_key? attribute
              nested_entity = Entity::MAP[attribute]
              value = hash[attribute].map { |e| instance_from(nested_entity, e) }
            end
            instance.public_send("#{attribute}=", value)
          end
        end
        instance
      end
    end
  end
end

{'fraction_non_alphanumeric': 0.09450402144772117, 'fraction_numerical': 0.01260053619302949, 'mean_word_length': 2.039103869653768, 'pattern_counts': {'":': 0, '<': 15, '<?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': '2102765', 'n_tokens_mistral': 2216, 'n_tokens_neox': 2088, 'n_words': 566}