diff --git a/rubygem/Gemfile.lock b/rubygem/Gemfile.lock index 9a41d99..904694a 100644 --- a/rubygem/Gemfile.lock +++ b/rubygem/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - dstk (0.50.2) + dstk (0.51.0) httmultiparty httparty json @@ -12,12 +12,11 @@ GEM httmultiparty (0.3.10) httparty (>= 0.7.3) multipart-post - httparty (0.11.0) - multi_json (~> 1.0) + httparty (0.12.0) + json (~> 1.8) multi_xml (>= 0.5.2) - json (1.8.0) - multi_json (1.7.6) - multi_xml (0.5.4) + json (1.8.1) + multi_xml (0.5.5) multipart-post (1.2.0) PLATFORMS diff --git a/rubygem/dstk-0.50.3.gem b/rubygem/dstk-0.50.3.gem deleted file mode 100644 index f39287c..0000000 Binary files a/rubygem/dstk-0.50.3.gem and /dev/null differ diff --git a/rubygem/dstk-0.51.0.gem b/rubygem/dstk-0.51.0.gem new file mode 100644 index 0000000..621f21a Binary files /dev/null and b/rubygem/dstk-0.51.0.gem differ diff --git a/rubygem/dstk.gemspec b/rubygem/dstk.gemspec index c1c91e2..69b8728 100644 --- a/rubygem/dstk.gemspec +++ b/rubygem/dstk.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = 'dstk' - s.version = '0.50.3' + s.version = '0.51.0' s.date = '2013-07-02' s.summary = "Data Science Toolkit client" s.description = "An interface to the datasciencetoolkit.org open API for geocoding addresses, extracting entities and sentiment from unstructured text, and other common semantic and geo data tasks." diff --git a/rubygem/lib/dstk.rb b/rubygem/lib/dstk.rb index 8eecbbe..09ef190 100644 --- a/rubygem/lib/dstk.rb +++ b/rubygem/lib/dstk.rb @@ -10,142 +10,122 @@ module DSTK class DSTK + def initialize(options = {}) default_options = { :api_base => 'http://www.datasciencetoolkit.org', :check_version => true, } - if ENV['DSTK_API_BASE'] - default_options[:api_base] = ENV['DSTK_API_BASE'] - end + default_options[:api_base] = ENV['DSTK_API_BASE'] if ENV['DSTK_API_BASE'] default_options.each do |key, value| - if !options.has_key?(key) - options[key] = value - end + options[key] = value if !options.has_key?(key) end - - @api_base = options[:api_base] - if options[:check_version] - self.check_version() - end + @dstk_api_base = options[:api_base] + + self.check_version() if options[:check_version] end - # A short-hand method to URL encode a string. See http://web.elctech.com/?p=58 + ############### UTILITIES ################### + # a short-hand method to URL encode a string. See http://web.elctech.com/?p=58 def u(str) str.gsub(/[^a-zA-Z0-9_\.\-]/n) {|s| sprintf('%%%02x', s[0]) } end - def json_api_call(endpoint, arguments = {}, data_payload = nil, data_payload_type = 'json') + # build the api url + def api_url(endpoint) + api_url = @dstk_api_base + endpoint + end - api_url = @api_base + endpoint - arguments_list = arguments.map do |name, value| - name + '=' + URI.encode(value) - end - if arguments_list.length > 0 - arguments_string = '?' + arguments_list.join('&') - api_url += arguments_string - end - response = nil - if !data_payload - response = HTTParty.get(api_url) - else - if data_payload_type == 'json' - data_payload_value = data_payload.to_json - else - data_payload_value = data_payload - end - response = HTTParty.post(api_url, { :body => data_payload_value }) - end + # convert payload to json if type json + def prep_payload(data_payload, data_payload_type) + data_payload_type == 'json' ? data_payload.to_json : data_payload + end + + # item should be an array. if it's not, make it one + def ensure_array(item) + item.is_a?(Array) ? item : [item] + end + ############### end UTILITIES ############### + + def dstk_api_call(endpoint, arguments = {}, data_payload = nil, data_payload_type = 'json') + response = if data_payload + HTTParty.post(api_url(endpoint), + { :body => prep_payload(data_payload, data_payload_type), + :query => arguments }) + else + HTTParty.get(api_url(endpoint), query: arguments) + end - if !response.body or response.code != 200 - raise "DSTK::json_api_call('#{endpoint}', #{arguments.to_json}, '#{data_payload}', '#{data_payload_type}') call to '#{api_url}' failed with code #{response.code} : '#{response.message}'" + unless response.body && response.code == 200 + raise "DSTK::dstk_api_call('#{endpoint}', #{arguments.to_json}, '#{data_payload}', '#{data_payload_type}') call to '#{response.request.uri.to_s}' failed with code #{response.code} : '#{response.message}'" end - json_string = response.body - result = nil begin - result = JSON.parse(json_string) + result = JSON.parse(response.body) + !result.is_a?(Array) && result['error'] ? raise(result['error']) : result rescue JSON::ParseError => e - raise "DSTK::json_api_call('#{endpoint}', #{arguments.to_json}, '#{data_payload}', '#{data_payload_type}') call to '#{api_url}' failed to parse response '#{json_string}' as JSON - #{e.message}" - end - if !result.is_a?(Array) and result['error'] - raise result['error'] + raise "DSTK::dstk_api_call('#{endpoint}', #{arguments.to_json}, '#{data_payload}', '#{data_payload_type}') call to '#{response.request.uri.to_s}' failed to parse response '#{response.body}' as JSON - #{e.message}" end - result end def check_version required_version = 50 - response = json_api_call('/info') + response = dstk_api_call('/info') actual_version = response['version'] if actual_version < required_version raise "DSTK: Version #{actual_version.to_s} found but #{required_version.to_s} is required" end end + def geocode(address) + dstk_api_call('/maps/api/geocode/json', { 'address' => address }) + end + def ip2coordinates(ips) - if !ips.is_a?(Array) then ips = [ips] end - response = json_api_call('/ip2coordinates', {}, ips) - response + dstk_api_call('/ip2coordinates', {}, ensure_array(ips), 'json') end def street2coordinates(addresses) - if !addresses.is_a?(Array) then addresses = [addresses] end - response = json_api_call('/street2coordinates', {}, addresses) - response - end - - def geocode(address) - response = json_api_call('/maps/api/geocode/json', { 'address' => address }) - response + dstk_api_call('/street2coordinates', {}, ensure_array(addresses), 'json') end def coordinates2politics(coordinates) - response = json_api_call('/coordinates2politics', {}, coordinates) - response + dstk_api_call('/coordinates2politics', {}, coordinates, 'json') end def text2places(text) - response = json_api_call('/text2places', {}, text, 'string') - response + dstk_api_call('/text2places', {}, text, 'string') end def file2text(inputfile) - response = json_api_call('/text2places', {}, {:inputfile => inputfile}, 'file') - response + dstk_api_call('/file2text', {}, {:inputfile => inputfile}, 'file') end def text2sentences(text) - response = json_api_call('/text2sentences', {}, text, 'string') - response + dstk_api_call('/text2sentences', {}, text, 'string') end def html2text(html) - response = json_api_call('/html2text', {}, html, 'string') - response + dstk_api_call('/html2text', {}, html, 'string') end def html2story(html) - response = json_api_call('/html2story', {}, html, 'string') - response + dstk_api_call('/html2story', {}, html, 'string') end def text2people(text) - response = json_api_call('/text2people', {}, text, 'string') - response + dstk_api_call('/text2people', {}, text, 'string') end def text2times(text) - response = json_api_call('/text2times', {}, text, 'string') - response + dstk_api_call('/text2times', {}, text, 'string') end def text2sentiment(text) - response = json_api_call('/text2sentiment', {}, text, 'string') - response + dstk_api_call('/text2sentiment', {}, text, 'string') end def coordinates2statistics(coordinates, statistics = nil) @@ -155,8 +135,12 @@ def coordinates2statistics(coordinates, statistics = nil) else arguments = {} end - response = json_api_call('/coordinates2statistics', arguments, coordinates) - response + + dstk_api_call('/coordinates2statistics', arguments, coordinates, 'json') + end + + def twofishes(text) + dstk_api_call('/twofishes', { 'query' => text }) end end diff --git a/rubygem/test/test_dstk.rb b/rubygem/test/test_dstk.rb index 9cda696..d8a73c1 100644 --- a/rubygem/test/test_dstk.rb +++ b/rubygem/test/test_dstk.rb @@ -91,4 +91,11 @@ def test_coordinates2statistics response = @dstk.coordinates2statistics(input, 'population_density') assert_equal expected, response end + + def test_twofishes + input = "pizza القاهرة" + expected = {"interpretations"=> [{"what"=>"pizza", "where"=>"القاهرة", "feature"=> {"cc"=>"EG", "geometry"=> {"center"=>{"lat"=>30.06263, "lng"=>31.24967}, "bounds"=> {"ne"=>{"lat"=>30.1480960846, "lng"=>31.3563537598}, "sw"=>{"lat"=>29.9635601044, "lng"=>31.1625480652}}}, "name"=>"Cairo", "displayName"=>"Cairo, EG", "woeType"=>7, "ids"=>[{"source"=>"geonameid", "id"=>"360630"}], "names"=> [{"name"=>"Cairo", "lang"=>"en", "flags"=>[16, 1]}, {"name"=>"Cairo", "lang"=>"en", "flags"=>[16]}], "highlightedName"=>"القاهرة, EG", "matchedName"=>"القاهرة, EG", "id"=>"geonameid:360630", "attributes"=> {"adm0cap"=>1, "scalerank"=>0, "labelrank"=>3, "natscale"=>600, "population"=>7734614}, "longId"=>"72057594038288566"}, "scores"=>{}}]} + response = @dstk.twofishes(input) + assert_equal expected, response + end end