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.
- data/History.txt +38 -0
- data/LICENSE.txt +202 -0
- data/Manifest.txt +69 -0
- data/NOTICE.txt +4 -0
- data/README.txt +105 -0
- data/Rakefile +20 -0
- data/bin/ruby-aws +9 -0
- data/lib/amazon/util.rb +10 -0
- data/lib/amazon/util/binder.rb +44 -0
- data/lib/amazon/util/data_reader.rb +157 -0
- data/lib/amazon/util/filter_chain.rb +79 -0
- data/lib/amazon/util/hash_nesting.rb +93 -0
- data/lib/amazon/util/lazy_results.rb +59 -0
- data/lib/amazon/util/logging.rb +23 -0
- data/lib/amazon/util/paginated_iterator.rb +70 -0
- data/lib/amazon/util/proactive_results.rb +116 -0
- data/lib/amazon/util/threadpool.rb +129 -0
- data/lib/amazon/util/user_data_store.rb +100 -0
- data/lib/amazon/webservices/mechanical_turk.rb +117 -0
- data/lib/amazon/webservices/mechanical_turk_requester.rb +261 -0
- data/lib/amazon/webservices/mturk/mechanical_turk_error_handler.rb +136 -0
- data/lib/amazon/webservices/mturk/question_generator.rb +58 -0
- data/lib/amazon/webservices/util/amazon_authentication_relay.rb +64 -0
- data/lib/amazon/webservices/util/command_line.rb +156 -0
- data/lib/amazon/webservices/util/convenience_wrapper.rb +90 -0
- data/lib/amazon/webservices/util/filter_proxy.rb +45 -0
- data/lib/amazon/webservices/util/mock_transport.rb +70 -0
- data/lib/amazon/webservices/util/request_signer.rb +42 -0
- data/lib/amazon/webservices/util/rest_transport.rb +108 -0
- data/lib/amazon/webservices/util/soap_simplifier.rb +48 -0
- data/lib/amazon/webservices/util/soap_transport.rb +38 -0
- data/lib/amazon/webservices/util/soap_transport_header_handler.rb +27 -0
- data/lib/amazon/webservices/util/unknown_result_exception.rb +27 -0
- data/lib/amazon/webservices/util/validation_exception.rb +55 -0
- data/lib/amazon/webservices/util/xml_simplifier.rb +61 -0
- data/lib/ruby-aws.rb +21 -0
- data/lib/ruby-aws/version.rb +8 -0
- data/samples/mturk/best_image/BestImage.rb +61 -0
- data/samples/mturk/best_image/best_image.properties +39 -0
- data/samples/mturk/best_image/best_image.question +82 -0
- data/samples/mturk/blank_slate/BlankSlate.rb +63 -0
- data/samples/mturk/blank_slate/BlankSlate_multithreaded.rb +67 -0
- data/samples/mturk/helloworld/MTurkHelloWorld.rb +56 -0
- data/samples/mturk/helloworld/mturk.yml +8 -0
- data/samples/mturk/reviewer/Reviewer.rb +103 -0
- data/samples/mturk/reviewer/mturk.yml +8 -0
- data/samples/mturk/simple_survey/SimpleSurvey.rb +90 -0
- data/samples/mturk/simple_survey/simple_survey.question +30 -0
- data/samples/mturk/site_category/SiteCategory.rb +87 -0
- data/samples/mturk/site_category/externalpage.htm +71 -0
- data/samples/mturk/site_category/site_category.input +6 -0
- data/samples/mturk/site_category/site_category.properties +45 -0
- data/samples/mturk/site_category/site_category.question +9 -0
- data/test/mturk/test_changehittypeofhit.rb +130 -0
- data/test/mturk/test_error_handler.rb +135 -0
- data/test/mturk/test_mechanical_turk_requester.rb +178 -0
- data/test/mturk/test_mock_mechanical_turk_requester.rb +205 -0
- data/test/test_ruby-aws.rb +22 -0
- data/test/unit/test_binder.rb +89 -0
- data/test/unit/test_data_reader.rb +135 -0
- data/test/unit/test_exceptions.rb +32 -0
- data/test/unit/test_hash_nesting.rb +93 -0
- data/test/unit/test_lazy_results.rb +89 -0
- data/test/unit/test_mock_transport.rb +132 -0
- data/test/unit/test_paginated_iterator.rb +58 -0
- data/test/unit/test_proactive_results.rb +108 -0
- data/test/unit/test_question_generator.rb +54 -0
- data/test/unit/test_threadpool.rb +50 -0
- data/test/unit/test_user_data_store.rb +80 -0
- metadata +158 -0
data/lib/amazon/util.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
|
2
|
+
# License:: Apache License, Version 2.0
|
3
|
+
|
4
|
+
require 'amazon/util/logging'
|
5
|
+
require 'amazon/util/paginated_iterator'
|
6
|
+
require 'amazon/util/lazy_results'
|
7
|
+
require 'amazon/util/proactive_results'
|
8
|
+
require 'amazon/util/binder'
|
9
|
+
require 'amazon/util/data_reader'
|
10
|
+
require 'amazon/util/threadpool'
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
|
2
|
+
# License:: Apache License, Version 2.0
|
3
|
+
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
module Amazon
|
7
|
+
module Util
|
8
|
+
|
9
|
+
# Simple class for holding eval information
|
10
|
+
# useful for feeding to ERB templates and the like
|
11
|
+
class Binder
|
12
|
+
|
13
|
+
def initialize(initial={},&block) # :yields: self
|
14
|
+
initial.each {|k,v| set(k,v) }
|
15
|
+
yield self unless block.nil?
|
16
|
+
end
|
17
|
+
|
18
|
+
def merge(hash)
|
19
|
+
hash.each {|k,v| set(k,v) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def set(k,v)
|
23
|
+
self.instance_variable_set "@#{k.to_s}", "#{v.to_s}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def bind
|
27
|
+
binding
|
28
|
+
end
|
29
|
+
|
30
|
+
# Helper method to simplify ERB evaluation
|
31
|
+
def erb_eval( template )
|
32
|
+
buffer = ""
|
33
|
+
c = ERB::Compiler.new("")
|
34
|
+
c.put_cmd = "buffer <<" if c.respond_to? :put_cmd=
|
35
|
+
c.insert_cmd = "buffer <<" if c.respond_to? :insert_cmd=
|
36
|
+
compiled = c.compile template
|
37
|
+
eval compiled
|
38
|
+
return buffer
|
39
|
+
end
|
40
|
+
|
41
|
+
end # Binder
|
42
|
+
|
43
|
+
end # Amazon::Util
|
44
|
+
end # Amazon
|
@@ -0,0 +1,157 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
|
2
|
+
# License:: Apache License, Version 2.0
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
require 'csv'
|
6
|
+
require 'amazon/util/hash_nesting'
|
7
|
+
|
8
|
+
module Amazon
|
9
|
+
module Util
|
10
|
+
|
11
|
+
# DataReader is a class for loading in data files. It is used to support bulk file-based operations.
|
12
|
+
# DataReader supports a number of different formats:
|
13
|
+
# * YAML
|
14
|
+
# * Tabular
|
15
|
+
# * CSV
|
16
|
+
# * Java Properties
|
17
|
+
# By default, DataReader assumes Tabular, but load and save both support your choice of format
|
18
|
+
class DataReader
|
19
|
+
|
20
|
+
attr_accessor :data
|
21
|
+
|
22
|
+
def initialize(data=[])
|
23
|
+
@data = data
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](index)
|
27
|
+
return @data[index]
|
28
|
+
end
|
29
|
+
|
30
|
+
def []=(index)
|
31
|
+
return @data[index]
|
32
|
+
end
|
33
|
+
|
34
|
+
def load( filename, format=:Tabular )
|
35
|
+
return {} unless File.exists? filename
|
36
|
+
raw_data = File.read( filename )
|
37
|
+
case format
|
38
|
+
when :Tabular
|
39
|
+
@data = parse_csv( raw_data, "\t" )
|
40
|
+
when :YAML
|
41
|
+
@data = YAML.load( raw_data ) || {}
|
42
|
+
when :CSV
|
43
|
+
@data = parse_csv( raw_data )
|
44
|
+
when :Properties
|
45
|
+
@data = parse_properties( raw_data )
|
46
|
+
else
|
47
|
+
raise "invalid format. options are :Tabular, :YAML, :CSV, :Properties"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def save( filename, format=:Tabular, force_headers=false )
|
52
|
+
return if @data.nil? or @data.empty?
|
53
|
+
existing = File.exists?( filename ) && File.size( filename ) > 0
|
54
|
+
File.open( filename, 'a+' ) {|f|
|
55
|
+
f << case format
|
56
|
+
when :Tabular
|
57
|
+
generate_csv( @data, force_headers || !existing, "\t" )
|
58
|
+
when :YAML
|
59
|
+
YAML.dump( @data )
|
60
|
+
when :CSV
|
61
|
+
generate_csv( @data, force_headers || !existing )
|
62
|
+
when :Properties
|
63
|
+
generate_properties( @data )
|
64
|
+
end
|
65
|
+
f << "\n" # adding a newline on the end, so appending is happy
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.load( filename, format=:Tabular )
|
70
|
+
reader = DataReader.new()
|
71
|
+
reader.load( filename, format )
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.save( filename, data, format=:Tabular, force_headers=false )
|
75
|
+
reader = DataReader.new( data )
|
76
|
+
reader.save( filename, format, force_headers )
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def parse_csv( raw_data, delim=nil )
|
82
|
+
processed = []
|
83
|
+
rows = CSV.parse( raw_data, delim )
|
84
|
+
return parse_rows( rows )
|
85
|
+
end
|
86
|
+
|
87
|
+
def parse_rows( rows )
|
88
|
+
processed = []
|
89
|
+
headers = rows.shift
|
90
|
+
for row in rows
|
91
|
+
item = {}
|
92
|
+
headers.each_index do |i|
|
93
|
+
item[headers[i].to_sym] = correct_type(row[i]) unless row[i].nil? or row[i].empty?
|
94
|
+
end
|
95
|
+
item.extend HashNesting
|
96
|
+
processed << item.unnest
|
97
|
+
end
|
98
|
+
return processed
|
99
|
+
end
|
100
|
+
|
101
|
+
def split_data( data )
|
102
|
+
data = data.collect {|d| d.extend(HashNesting).nest }
|
103
|
+
headers = data[0].keys.sort
|
104
|
+
rows = data.collect { |item|
|
105
|
+
row = []
|
106
|
+
item.keys.each {|k|
|
107
|
+
headers << k unless headers.include? k
|
108
|
+
index = headers.index k
|
109
|
+
row[index] = item[k].to_s
|
110
|
+
}
|
111
|
+
row
|
112
|
+
}
|
113
|
+
return headers, rows
|
114
|
+
end
|
115
|
+
|
116
|
+
def generate_csv( data, dump_header, delim=nil )
|
117
|
+
return "" if data.nil? or data.empty?
|
118
|
+
headers, rows = split_data( data )
|
119
|
+
return generate_rows( headers, rows, dump_header, delim )
|
120
|
+
end
|
121
|
+
|
122
|
+
def generate_rows( headers, rows, dump_header, record_seperator=nil )
|
123
|
+
rows.unshift headers if dump_header
|
124
|
+
buff = rows.collect { |row|
|
125
|
+
CSV.generate_line( row, record_seperator )
|
126
|
+
}
|
127
|
+
return buff.join("\n")
|
128
|
+
end
|
129
|
+
|
130
|
+
def parse_properties( raw_data )
|
131
|
+
processed = {}
|
132
|
+
for line in raw_data.split(/\n\r?/)
|
133
|
+
next if line =~ /^\W*(#.*)?$/ # ignore lines beginning w/ comments
|
134
|
+
if md = /^([^:=]+)[=:](.*)/.match(line)
|
135
|
+
processed[md[1].strip] = correct_type(md[2].strip)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
processed.extend HashNesting
|
139
|
+
return processed.unnest
|
140
|
+
end
|
141
|
+
|
142
|
+
def generate_properties( raw_data )
|
143
|
+
raw_data.extend HashNesting
|
144
|
+
(raw_data.nest.collect {|k,v| "#{k}:#{v}" }).join("\n")
|
145
|
+
end
|
146
|
+
|
147
|
+
# convert to integer if possible
|
148
|
+
def correct_type( str )
|
149
|
+
return str.to_f if str =~ /^\d+\.\d+$/ unless str =~ /^0\d/
|
150
|
+
return str.to_i if str =~ /^\d+$/ unless str =~ /^0\d/
|
151
|
+
return str
|
152
|
+
end
|
153
|
+
|
154
|
+
end # DataReader
|
155
|
+
|
156
|
+
end # Amazon::Util
|
157
|
+
end # Amazon
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
|
2
|
+
# License:: Apache License, Version 2.0
|
3
|
+
|
4
|
+
module Amazon
|
5
|
+
module Util
|
6
|
+
|
7
|
+
# A class for managing around style interceptors,
|
8
|
+
# which can be used to implement a decorator design pattern.
|
9
|
+
class FilterChain
|
10
|
+
|
11
|
+
class Filter
|
12
|
+
|
13
|
+
attr_reader :name, :filter_params, :filter_block
|
14
|
+
|
15
|
+
def initialize( name, filter_params, filter_block )
|
16
|
+
@name = name
|
17
|
+
@filter_params = filter_params
|
18
|
+
@filter_block = filter_block
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute( chain, block_params )
|
22
|
+
@filter_block.call( chain, block_params, *@filter_params )
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :filters
|
28
|
+
|
29
|
+
def initialize()
|
30
|
+
@filters = []
|
31
|
+
end
|
32
|
+
|
33
|
+
def execute( *block_params, &block )
|
34
|
+
if @filters.size == 0
|
35
|
+
block.call( *block_params )
|
36
|
+
else
|
37
|
+
create_chain( @filters, 0, block, block_params ).call
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def add( name=nil, *filter_params, &filter_block )
|
42
|
+
add_filter( Filter.new( name, filter_params, filter_block ) )
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_filter( filter )
|
46
|
+
if !filter.name.nil?
|
47
|
+
@filters.each_with_index { |existing_filter,i|
|
48
|
+
if filter.name == existing_filter.name
|
49
|
+
@filters[i] = filter
|
50
|
+
return
|
51
|
+
end
|
52
|
+
}
|
53
|
+
end
|
54
|
+
@filters << filter
|
55
|
+
end
|
56
|
+
|
57
|
+
def remove( name )
|
58
|
+
@filters.delete_if { |filter| name == filter.name }
|
59
|
+
end
|
60
|
+
|
61
|
+
def remove_all()
|
62
|
+
@filters.clear
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def create_chain( filters, pos, block, block_params )
|
68
|
+
if pos >= filters.size
|
69
|
+
return proc{ block.call( *block_params ) }
|
70
|
+
else
|
71
|
+
chain = create_chain( filters, pos+1, block, block_params )
|
72
|
+
return proc { filters[pos].execute( chain, block_params ) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end # Amazon::Util
|
79
|
+
end # Amazon
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
|
2
|
+
# License:: Apache License, Version 2.0
|
3
|
+
|
4
|
+
module Amazon
|
5
|
+
module Util
|
6
|
+
|
7
|
+
module HashNesting
|
8
|
+
|
9
|
+
def nest
|
10
|
+
result = {}.extend HashNesting
|
11
|
+
primaryKeys.each { |key| traverse_nest( "#{key}", self[key] ) { |k,v| result[k] = v } }
|
12
|
+
result
|
13
|
+
end
|
14
|
+
|
15
|
+
def nest!
|
16
|
+
keys = primaryKeys
|
17
|
+
tmp = self.dup
|
18
|
+
self.keys.each { |k| self.delete k}
|
19
|
+
keys.each { |key| traverse_nest( "#{key}", tmp[key] ) { |k,v| self[k] = v} }
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def unnest
|
24
|
+
result = {}.extend HashNesting
|
25
|
+
for key in primaryKeys
|
26
|
+
true_keys = key.to_s.split('.')
|
27
|
+
resolve_nesting( result, self[key], *true_keys)
|
28
|
+
end
|
29
|
+
result
|
30
|
+
end
|
31
|
+
|
32
|
+
def unnest!
|
33
|
+
for key in primaryKeys
|
34
|
+
true_keys = key.to_s.split('.')
|
35
|
+
value = self[key]
|
36
|
+
self.delete key
|
37
|
+
resolve_nesting( self, value, *true_keys)
|
38
|
+
end
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# if hash has both string and symbol keys, symbol wins
|
45
|
+
def primaryKeys
|
46
|
+
sym_keys = []
|
47
|
+
str_keys = []
|
48
|
+
self.keys.each { |k|
|
49
|
+
case k
|
50
|
+
when Symbol
|
51
|
+
sym_keys << k
|
52
|
+
when String
|
53
|
+
str_keys << k
|
54
|
+
else
|
55
|
+
str_keys << k
|
56
|
+
end
|
57
|
+
}
|
58
|
+
str_keys.delete_if {|k| sym_keys.member? k.to_s.to_sym }
|
59
|
+
sym_keys + str_keys
|
60
|
+
end
|
61
|
+
|
62
|
+
def resolve_nesting( dest, data, *keys )
|
63
|
+
return data if keys.empty?
|
64
|
+
dest ||= {}
|
65
|
+
key = keys.shift.to_sym
|
66
|
+
if keys.first.to_i.to_s == keys.first
|
67
|
+
# array
|
68
|
+
index = keys.shift.to_i - 1
|
69
|
+
raise "illegal index: #{keys.join '.'} index must be >= 1" if index < 0
|
70
|
+
dest[key] ||= []
|
71
|
+
dest[key][index] = resolve_nesting( dest[key][index], data, *keys )
|
72
|
+
else
|
73
|
+
# hash
|
74
|
+
dest[key] = resolve_nesting( dest[key], data, *keys )
|
75
|
+
end
|
76
|
+
dest
|
77
|
+
end
|
78
|
+
|
79
|
+
def traverse_nest( namespace, data, &block )
|
80
|
+
case data.class.to_s
|
81
|
+
when 'Array'
|
82
|
+
data.each_with_index { |v,i| traverse_nest( "#{namespace}.#{i+1}", v, &block ) }
|
83
|
+
when 'Hash'
|
84
|
+
data.each { |k,v| traverse_nest( "#{namespace}.#{k}", v, &block ) }
|
85
|
+
else
|
86
|
+
yield namespace, data.to_s
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end # HashNesting
|
91
|
+
|
92
|
+
end # Amazon::Util
|
93
|
+
end # Amazon
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Copyright:: Copyright (c) 2007 Amazon Technologies, Inc.
|
2
|
+
# License:: Apache License, Version 2.0
|
3
|
+
|
4
|
+
require 'amazon/util/paginated_iterator'
|
5
|
+
|
6
|
+
module Amazon
|
7
|
+
module Util
|
8
|
+
|
9
|
+
# This class provides a wrapper for lazy evaluation of results.
|
10
|
+
# The constructor takes a block which should accept a pagenumber
|
11
|
+
# and return a page worth of results.
|
12
|
+
class LazyResults
|
13
|
+
include Enumerable
|
14
|
+
|
15
|
+
def initialize( &feeder )
|
16
|
+
@iterator = PaginatedIterator.new( &feeder )
|
17
|
+
flush
|
18
|
+
end
|
19
|
+
|
20
|
+
# clear the result set and start over again
|
21
|
+
def flush
|
22
|
+
@truth = []
|
23
|
+
@iterator.restart
|
24
|
+
end
|
25
|
+
|
26
|
+
# iterate over entire result set, loading lazily
|
27
|
+
def each( &block ) # :yields: item
|
28
|
+
@truth.each {|e| yield e }
|
29
|
+
@iterator.each {|e| @truth << e ; yield e }
|
30
|
+
end
|
31
|
+
|
32
|
+
# index into the array set. if requested index has not been loaded, will load up to that index
|
33
|
+
def []( index )
|
34
|
+
feedme while !@iterator.done and index >= @truth.size
|
35
|
+
return @truth[index]
|
36
|
+
end
|
37
|
+
|
38
|
+
# fully populate the result set and return a true array
|
39
|
+
def to_a
|
40
|
+
feedme until @iterator.done
|
41
|
+
return @truth.dup
|
42
|
+
end
|
43
|
+
|
44
|
+
def inspect # :nodoc:
|
45
|
+
"#<Amazon::Util::LazyResults truth_size=#{@truth.size} page=#{@page} done=#{@done}>"
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# fetch the next item from the iterator and stick it in @truth
|
51
|
+
def feedme
|
52
|
+
item = @iterator.next
|
53
|
+
@truth << item unless item.nil?
|
54
|
+
end
|
55
|
+
|
56
|
+
end # LazyResults
|
57
|
+
|
58
|
+
end # Amazon::Util
|
59
|
+
end # Amazon
|