dbgrandi-ruby-aws 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/History.txt +38 -0
  2. data/LICENSE.txt +202 -0
  3. data/Manifest.txt +69 -0
  4. data/NOTICE.txt +4 -0
  5. data/README.txt +105 -0
  6. data/Rakefile +20 -0
  7. data/bin/ruby-aws +9 -0
  8. data/lib/amazon/util.rb +10 -0
  9. data/lib/amazon/util/binder.rb +44 -0
  10. data/lib/amazon/util/data_reader.rb +157 -0
  11. data/lib/amazon/util/filter_chain.rb +79 -0
  12. data/lib/amazon/util/hash_nesting.rb +93 -0
  13. data/lib/amazon/util/lazy_results.rb +59 -0
  14. data/lib/amazon/util/logging.rb +23 -0
  15. data/lib/amazon/util/paginated_iterator.rb +70 -0
  16. data/lib/amazon/util/proactive_results.rb +116 -0
  17. data/lib/amazon/util/threadpool.rb +129 -0
  18. data/lib/amazon/util/user_data_store.rb +100 -0
  19. data/lib/amazon/webservices/mechanical_turk.rb +117 -0
  20. data/lib/amazon/webservices/mechanical_turk_requester.rb +261 -0
  21. data/lib/amazon/webservices/mturk/mechanical_turk_error_handler.rb +136 -0
  22. data/lib/amazon/webservices/mturk/question_generator.rb +58 -0
  23. data/lib/amazon/webservices/util/amazon_authentication_relay.rb +64 -0
  24. data/lib/amazon/webservices/util/command_line.rb +156 -0
  25. data/lib/amazon/webservices/util/convenience_wrapper.rb +90 -0
  26. data/lib/amazon/webservices/util/filter_proxy.rb +45 -0
  27. data/lib/amazon/webservices/util/mock_transport.rb +70 -0
  28. data/lib/amazon/webservices/util/request_signer.rb +42 -0
  29. data/lib/amazon/webservices/util/rest_transport.rb +108 -0
  30. data/lib/amazon/webservices/util/soap_simplifier.rb +48 -0
  31. data/lib/amazon/webservices/util/soap_transport.rb +38 -0
  32. data/lib/amazon/webservices/util/soap_transport_header_handler.rb +27 -0
  33. data/lib/amazon/webservices/util/unknown_result_exception.rb +27 -0
  34. data/lib/amazon/webservices/util/validation_exception.rb +55 -0
  35. data/lib/amazon/webservices/util/xml_simplifier.rb +61 -0
  36. data/lib/ruby-aws.rb +21 -0
  37. data/lib/ruby-aws/version.rb +8 -0
  38. data/samples/mturk/best_image/BestImage.rb +61 -0
  39. data/samples/mturk/best_image/best_image.properties +39 -0
  40. data/samples/mturk/best_image/best_image.question +82 -0
  41. data/samples/mturk/blank_slate/BlankSlate.rb +63 -0
  42. data/samples/mturk/blank_slate/BlankSlate_multithreaded.rb +67 -0
  43. data/samples/mturk/helloworld/MTurkHelloWorld.rb +56 -0
  44. data/samples/mturk/helloworld/mturk.yml +8 -0
  45. data/samples/mturk/reviewer/Reviewer.rb +103 -0
  46. data/samples/mturk/reviewer/mturk.yml +8 -0
  47. data/samples/mturk/simple_survey/SimpleSurvey.rb +90 -0
  48. data/samples/mturk/simple_survey/simple_survey.question +30 -0
  49. data/samples/mturk/site_category/SiteCategory.rb +87 -0
  50. data/samples/mturk/site_category/externalpage.htm +71 -0
  51. data/samples/mturk/site_category/site_category.input +6 -0
  52. data/samples/mturk/site_category/site_category.properties +45 -0
  53. data/samples/mturk/site_category/site_category.question +9 -0
  54. data/test/mturk/test_changehittypeofhit.rb +130 -0
  55. data/test/mturk/test_error_handler.rb +135 -0
  56. data/test/mturk/test_mechanical_turk_requester.rb +178 -0
  57. data/test/mturk/test_mock_mechanical_turk_requester.rb +205 -0
  58. data/test/test_ruby-aws.rb +22 -0
  59. data/test/unit/test_binder.rb +89 -0
  60. data/test/unit/test_data_reader.rb +135 -0
  61. data/test/unit/test_exceptions.rb +32 -0
  62. data/test/unit/test_hash_nesting.rb +93 -0
  63. data/test/unit/test_lazy_results.rb +89 -0
  64. data/test/unit/test_mock_transport.rb +132 -0
  65. data/test/unit/test_paginated_iterator.rb +58 -0
  66. data/test/unit/test_proactive_results.rb +108 -0
  67. data/test/unit/test_question_generator.rb +54 -0
  68. data/test/unit/test_threadpool.rb +50 -0
  69. data/test/unit/test_user_data_store.rb +80 -0
  70. metadata +158 -0
@@ -0,0 +1,108 @@
1
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
2
+ # License:: Apache License, Version 2.0
3
+
4
+ require 'cgi'
5
+ require 'net/http'
6
+ require 'rexml/document'
7
+ require 'amazon/webservices/util/xml_simplifier'
8
+
9
+ module Amazon
10
+ module WebServices
11
+ module Util
12
+
13
+ class RESTTransport
14
+
15
+ REQUIRED_PARAMETERS = [:Endpoint]
16
+
17
+ def self.canPost?
18
+ Net::HTTP.respond_to? :post_form
19
+ end
20
+
21
+ def initialize( args )
22
+ missing_parameters = REQUIRED_PARAMETERS - args.keys
23
+ raise "Missing paramters: #{missing_parameters.join(',')}" unless missing_parameters.empty?
24
+ @url = args[:Endpoint]
25
+ @httpMethod = resolveHTTPMethod( args[:RestStyle] )
26
+ @version = args[:Version]
27
+
28
+ agent = RubyAWS::agent( args[:SoftwareName] )
29
+ @headers = {
30
+ 'User-Agent' => agent,
31
+ 'X-Amazon-Software' => agent,
32
+ 'Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8',
33
+ }
34
+ end
35
+
36
+ def resolveHTTPMethod( method )
37
+ case method.to_s.upcase
38
+ when "GET"
39
+ return :GET
40
+ when "POST"
41
+ raise "Your version of Ruby does not support HTTP Post" unless RESTTransport.canPost?
42
+ return :POST
43
+ else
44
+ return ( RESTTransport.canPost? ? :POST : :GET )
45
+ end
46
+ end
47
+
48
+ def method_missing( method, *args )
49
+ params = { :Operation => method, :Version => @version }
50
+ params.merge!( args[0].delete( :Request )[0] )
51
+ params.merge!( args[0] )
52
+ res = nil
53
+ if @httpMethod == :GET
54
+ url = URI.parse( @url + toQueryString(params) )
55
+ res = Net::HTTP.new( url.host, url.port ).start { |http|
56
+ http.get( url.request_uri, @headers )
57
+ }.body
58
+ else
59
+ url = URI.parse( @url )
60
+ res = Net::HTTP.new( url.host, url.port ).start { |http|
61
+ req = Net::HTTP::Post.new( url.path, @headers )
62
+ req.form_data = toPostParams( params )
63
+ req['Content-Type'] = @headers['Content-Type'] # necessary because req.form_data resets Content-Type header
64
+ http.request( req )
65
+ }.body
66
+ end
67
+ xml = REXML::Document.new( res )
68
+ XMLSimplifier.simplify xml
69
+ end
70
+
71
+ private
72
+
73
+ def toQueryString(params)
74
+ queryString = ""
75
+ each_http_param(params) { |key,value|
76
+ queryString << ( '&' + key + '=' + CGI.escape(value) )
77
+ }
78
+ return queryString
79
+ end
80
+
81
+ def toPostParams(params)
82
+ postParams = {}
83
+ each_http_param(params) { |key,value|
84
+ postParams[key] = value }
85
+ return postParams
86
+ end
87
+
88
+ def each_http_param(params,&block)
89
+ params.each {|k,v| each_http_param_helper( k, v, false, &block ) unless v.nil? }
90
+ end
91
+
92
+ def each_http_param_helper(key,value,num=false,&block)
93
+ key = key.to_s
94
+ case value.class.to_s
95
+ when 'Array'
96
+ value.each_with_index { |v,i| each_http_param_helper( "#{key}.#{i+1}", v, true, &block ) unless v.nil? }
97
+ when 'Hash'
98
+ value.each { |k,v| each_http_param_helper( "#{key}#{num ? '.' : '.1.'}#{k}", v, false, &block ) unless v.nil? }
99
+ else
100
+ yield key, value.to_s
101
+ end
102
+ end
103
+
104
+ end # RESTTransport
105
+
106
+ end # Amazon::WebServices::Util
107
+ end # Amazon::WebServices
108
+ end # Amazon
@@ -0,0 +1,48 @@
1
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
2
+ # License:: Apache License, Version 2.0
3
+
4
+ module Amazon
5
+ module WebServices
6
+ module Util
7
+
8
+ class SOAPSimplifier
9
+
10
+ # simplify(item) -- convert a soap object into a simple nested hash
11
+ def self.simplify(item)
12
+ case item.class.to_s
13
+ when 'SOAP::Mapping::Object'
14
+ simple = {}
15
+ item.__xmlattr.each {|name,at| simple["*#{name}*"] = simplify(at)}
16
+ item.__xmlele.each { |element|
17
+ # element consists of a QName and a payload
18
+ name = element[0].name
19
+ payload = simplify(element[1])
20
+ simple[name.to_sym] = payload
21
+ }
22
+ simple
23
+ when 'Array'
24
+ item.collect {|i| simplify(i) }
25
+ else
26
+ str = item.to_s
27
+ case str
28
+ when /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z$/
29
+ Time.gm($1,$2,$3,$4,$5,$6)
30
+ when /^\d+$/
31
+ if str.to_i.to_s == str
32
+ str.to_i
33
+ else
34
+ str
35
+ end
36
+ when /^\d+\.\d+$/
37
+ str.to_f
38
+ else
39
+ str
40
+ end
41
+ end
42
+ end
43
+
44
+ end # Amazon::WebServices::Util::SoapSimplifier
45
+
46
+ end # Amazon::WebServices::Util
47
+ end # Amazon::WebServices
48
+ end # Amazon
@@ -0,0 +1,38 @@
1
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
2
+ # License:: Apache License, Version 2.0
3
+
4
+ require 'soap/wsdlDriver'
5
+ require 'amazon/webservices/util/soap_simplifier'
6
+ require 'amazon/webservices/util/soap_transport_header_handler'
7
+
8
+ module Amazon
9
+ module WebServices
10
+ module Util
11
+
12
+ class SOAPTransport
13
+
14
+ REQUIRED_PARAMETERS = [:Wsdl]
15
+
16
+ def self.canSOAP?
17
+ SOAP::Version >= "1.5.5"
18
+ end
19
+
20
+ def initialize( args )
21
+ raise "SOAP version 1.5.5+ (included in Ruby 1.8.3+) required to use SOAP Transport" unless SOAPTransport::canSOAP?
22
+
23
+ missing_parameters = REQUIRED_PARAMETERS - args.keys
24
+ raise "Missing paramters: #{missing_parameters.join(',')}" unless missing_parameters.empty?
25
+ @driver = SOAP::WSDLDriverFactory.new( args[:Wsdl] ).create_rpc_driver
26
+ @driver.endpoint_url = args[:Endpoint] unless args[:Endpoint].nil?
27
+ @driver.headerhandler << SOAPTransportHeaderHandler.new('http://amazonaws.com/header', 'X-Amazon-Software', RubyAWS::agent(args[:SoftwareName]) )
28
+ end
29
+
30
+ def method_missing( method, *args )
31
+ SOAPSimplifier.simplify @driver.send( method, *args )
32
+ end
33
+
34
+ end # SOAPTransport
35
+
36
+ end # Amazon::WebServices::Util
37
+ end # Amazon::WebServices
38
+ end # Amazon
@@ -0,0 +1,27 @@
1
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
2
+ # License:: Apache License, Version 2.0
3
+
4
+ require 'soap/header/simplehandler.rb'
5
+ require 'xsd/qname.rb'
6
+
7
+ module Amazon
8
+ module WebServices
9
+ module Util
10
+
11
+ class SOAPTransportHeaderHandler < SOAP::Header::SimpleHandler
12
+
13
+ def initialize(ns, tag, value)
14
+ super(XSD::QName.new(ns, tag))
15
+ @tag = tag
16
+ @value = value
17
+ end
18
+
19
+ def on_simple_outbound
20
+ @value
21
+ end
22
+
23
+ end # SOAPTransportHeaderHandler
24
+
25
+ end # Amazon::WebServices::Util
26
+ end # Amazon::WebServices
27
+ end # Amazon
@@ -0,0 +1,27 @@
1
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
2
+ # License:: Apache License, Version 2.0
3
+
4
+ module Amazon
5
+ module WebServices
6
+ module Util
7
+
8
+ # This exception is thrown when we don't know if a service call succeeded or not
9
+ class UnknownResultException < RuntimeError
10
+
11
+ attr_reader :method, :args, :exception
12
+
13
+ def initialize( exception, method, args={} )
14
+ @method = method
15
+ @args = args
16
+ @exception = exception
17
+ end
18
+
19
+ def to_s
20
+ "UnknownResultException: got #{@exception} calling #{@method}"
21
+ end
22
+
23
+ end
24
+
25
+ end # Amazon::WebServices::Util
26
+ end # Amazon::WebServices
27
+ end # Amazon
@@ -0,0 +1,55 @@
1
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
2
+ # License:: Apache License, Version 2.0
3
+
4
+ module Amazon
5
+ module WebServices
6
+ module Util
7
+
8
+ class ValidationException < RuntimeError
9
+
10
+ attr_reader :message, :description, :result
11
+
12
+ def initialize( result, message=nil )
13
+ @result = result
14
+
15
+ @message = [
16
+ message,
17
+ get_nested_key( result, :OperationRequest, :Errors, :Error, :Code ),
18
+ get_nested_key( result, :Request, :Errors, :Error, :Code ),
19
+ get_nested_key( result, :Errors, :Error, :Code ),
20
+ ].detect { |v| !v.nil? }
21
+
22
+ @description = [
23
+ get_nested_key( result, :OperationRequest, :Errors, :Error, :Message ),
24
+ get_nested_key( result, :Request, :Errors, :Error, :Message ),
25
+ get_nested_key( result, :Errors, :Error, :Message ),
26
+ ].detect { |v| !v.nil? }
27
+
28
+ end
29
+
30
+ def to_s
31
+ "ValidationException: #{message}"
32
+ end
33
+
34
+ private
35
+
36
+ def get_nested_key( hash, *keys )
37
+ return nil unless hash.kind_of?(Hash)
38
+ result = hash
39
+ if hash.key? keys.first
40
+ keys.each do |key|
41
+ return nil unless result.kind_of?(Hash)
42
+ result = result[key]
43
+ end
44
+ return result
45
+ else
46
+ nested = hash.collect { |k,v| get_nested_key( v, *keys ) }
47
+ return ([nested].flatten - [nil]).first
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ end # Amazon::WebServices::Util
54
+ end # Amazon::WebServices
55
+ end # Amazon
@@ -0,0 +1,61 @@
1
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
2
+ # License:: Apache License, Version 2.0
3
+
4
+ require 'rexml/document'
5
+
6
+ module Amazon
7
+ module WebServices
8
+ module Util
9
+
10
+ class XMLSimplifier
11
+
12
+ # simplify(xml) -- convert an xml document into a simple nested hash
13
+ def self.simplify(xml)
14
+ case xml.class.to_s
15
+ when 'REXML::Text'
16
+ {}
17
+ when 'REXML::Document'
18
+ xml.root.children.inject({}) {|data,child| self.merge( data, simplify(child) ) }
19
+ when 'REXML::Element'
20
+ if xml.children.size > 1 || xml.text.nil?
21
+ value = xml.children.inject({}) { |data,child| self.merge( data, simplify(child) ) }
22
+ { xml.name.to_sym => value }
23
+ else
24
+ str = xml.text
25
+ value = case str
26
+ when /^(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)Z$/
27
+ Time.gm($1,$2,$3,$4,$5,$6)
28
+ when /^\d+$/
29
+ if str.to_i.to_s == str
30
+ str.to_i
31
+ else
32
+ str
33
+ end
34
+ when /^\d+\.\d+$/
35
+ str.to_f
36
+ else
37
+ str
38
+ end
39
+ { xml.name.to_sym => value }
40
+ end
41
+ else
42
+ raise "XMLSimplifier -- failed to simplify: #{xml.inspect}"
43
+ end
44
+ end
45
+
46
+ def self.merge(hash1, hash2)
47
+ hash2.each_key { |key|
48
+ if hash1[key]
49
+ hash1[key] = [hash1[key], hash2[key]].flatten
50
+ else
51
+ hash1[key] = hash2[key]
52
+ end
53
+ }
54
+ hash1
55
+ end
56
+
57
+ end # Amazon::WebServices::Util::XMLSimplifier
58
+
59
+ end # Amazon::WebServices::Util
60
+ end # Amazon::WebServices
61
+ end # Amazon
@@ -0,0 +1,21 @@
1
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
2
+ # License:: Apache License, Version 2.0
3
+
4
+ require 'ruby-aws/version'
5
+
6
+ begin ; require 'rubygems' ; rescue LoadError => e ; end
7
+
8
+ require 'amazon/webservices/mechanical_turk_requester'
9
+
10
+ module RubyAWS
11
+
12
+ def self.agent(software_name="")
13
+ version = "ruby-aws/#{RubyAWS::VERSION}"
14
+ if software_name.to_s == ""
15
+ version
16
+ else
17
+ "#{version} #{software_name}"
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,8 @@
1
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
2
+ # License:: Apache License, Version 2.0
3
+
4
+ module RubyAWS
5
+ SRC_PATH = " $URL$ "
6
+ SRC_PATH =~ /tags\/(\d+\.\d+\.\d+)\/.*\/ruby-aws\/version.rb/
7
+ VERSION = ($1 || "0.0.1").freeze
8
+ end
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
4
+ # License:: Apache License, Version 2.0
5
+
6
+ begin ; require 'rubygems' ; rescue LoadError ; end
7
+
8
+ # The Best Image sample application will create a HIT asking a worker
9
+ # to choose the best of three images, given a set of criteria.
10
+ #
11
+ # The following concepts are covered:
12
+ # - Using the <FormattedContent> functionality in QuestionForm
13
+ # - File-based QuestionForm and HIT properties HIT loading
14
+ # - Using a basic system qualification
15
+
16
+ require 'ruby-aws'
17
+ @mturk = Amazon::WebServices::MechanicalTurkRequester.new :Host => :Sandbox
18
+
19
+ # Use this line instead if you want to talk to Prod
20
+ #@mturk = Amazon::WebServices::MechanicalTurkRequester.new :Host => :Production
21
+
22
+
23
+ # Check to see if your account has sufficient funds
24
+ def hasEnoughFunds?
25
+ available = @mturk.availableFunds
26
+ puts "Got account balance: %.2f" % available
27
+ return available > 0.055
28
+ end
29
+
30
+ def getHITUrl( hitTypeId )
31
+ if @mturk.host =~ /sandbox/
32
+ "http://workersandbox.mturk.com/mturk/preview?groupId=#{hitTypeId}" # Sandbox Url
33
+ else
34
+ "http://mturk.com/mturk/preview?groupId=#{hitTypeId}" # Production Url
35
+ end
36
+ end
37
+
38
+ # Create the BestImage HIT
39
+ def createBestImage
40
+
41
+ # Defining the location of the file containing the QuestionForm and the properties of the HIT
42
+ rootDir = File.dirname $0;
43
+ questionFile = rootDir + "/best_image.question";
44
+ propertiesFile = rootDir + "/best_image.properties";
45
+
46
+ # Loading configuration properties from a HIT properties file.
47
+ # In this sample, the qualification is defined in the properties file.
48
+ props = Amazon::Util::DataReader.load( propertiesFile, :Properties )
49
+ props[:Reward] = { :Amount => 0.05, :CurrencyCode => 'USD'}
50
+ # Loading the question (QuestionForm) file.
51
+ question = File.read( questionFile )
52
+ # no validation
53
+ result = @mturk.createHIT( {:Question => question}.merge(props) )
54
+ puts "Created HIT: #{result[:HITId]}"
55
+ puts "Url: #{getHITUrl( result[:HITTypeId] )}"
56
+
57
+ # save the HIT Id to a file so we don't lose it...
58
+ Amazon::Util::DataReader.save( File.join( rootDir, "hits_created" ), [{:HITId => result[:HITId] }], :Tabular )
59
+ end
60
+
61
+ createBestImage if hasEnoughFunds?