ruby-aaws 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- # $Id: search.rb,v 1.35 2009/05/26 16:27:12 ianmacd Exp $
1
+ # $Id: search.rb,v 1.43 2009/06/14 22:28:27 ianmacd Exp $
2
2
  #
3
3
 
4
4
  module Amazon
@@ -28,10 +28,17 @@ module Amazon
28
28
  #
29
29
  class LocaleError < Amazon::AWS::Error::AWSError; end
30
30
 
31
- # Requests can be authenticated using the SHA-256 Secure Hash
32
- # Algorithm.
31
+ # Do we have support for the SHA-256 Secure Hash Algorithm?
33
32
  #
34
- DIGEST = OpenSSL::Digest::Digest.new( 'sha256' )
33
+ # Note that Module#constants returns Strings in Ruby 1.8 and Symbols
34
+ # in 1.9.
35
+ #
36
+ DIGEST_SUPPORT = OpenSSL::Digest.constants.include?( 'SHA256' ) ||
37
+ OpenSSL::Digest.constants.include?( :SHA256 )
38
+
39
+ # Requests are authenticated using the SHA-256 Secure Hash Algorithm.
40
+ #
41
+ DIGEST = OpenSSL::Digest::Digest.new( 'sha256' ) if DIGEST_SUPPORT
35
42
 
36
43
  attr_reader :conn, :config, :locale, :query, :user_agent
37
44
  attr_writer :cache
@@ -40,9 +47,12 @@ module Amazon
40
47
  # This method is used to generate an AWS search request object.
41
48
  #
42
49
  # _key_id_ is your AWS {access key
43
- # ID}[https://aws-portal.amazon.com/gp/aws/developer/registration/index.html],
50
+ # ID}[https://aws-portal.amazon.com/gp/aws/developer/registration/index.html].
51
+ # Note that your secret key, used for signing requests, can be
52
+ # specified only in your <tt>~/.amazonrc</tt> configuration file.
53
+ #
44
54
  # _associate_ is your
45
- # Associates[http://docs.amazonwebservices.com/AWSECommerceService/2009-01-06/GSG/BecominganAssociate.html]
55
+ # Associates[http://docs.amazonwebservices.com/AWSECommerceService/2009-03-31/GSG/BecominganAssociate.html]
46
56
  # tag (if any), _locale_ is the locale in which you which to work
47
57
  # (*us* for amazon.com[http://www.amazon.com/], *uk* for
48
58
  # amazon.co.uk[http://www.amazon.co.uk], etc.), _cache_ is whether or
@@ -184,7 +194,7 @@ module Amazon
184
194
  # _xml_ is the XML node below which to search.
185
195
  #
186
196
  def error_check(xml)
187
- if xml = xml.elements['Errors/Error']
197
+ if ! xml.nil? && xml = xml.elements['Errors/Error']
188
198
  raise Amazon::AWS::Error.exception( xml )
189
199
  end
190
200
  end
@@ -195,7 +205,8 @@ module Amazon
195
205
  #
196
206
  def timestamp
197
207
  @query << '&Timestamp=%s' %
198
- [ Amazon.url_encode( Time.now.utc.strftime( '%FT%TZ' ) ) ]
208
+ [ Amazon.url_encode(
209
+ Time.now.utc.strftime( '%Y-%m-%dT%H:%M:%SZ' ) ) ]
199
210
  end
200
211
  private :timestamp
201
212
 
@@ -204,6 +215,8 @@ module Amazon
204
215
  # also adds a timestamp.
205
216
  #
206
217
  def sign
218
+ return false unless DIGEST_SUPPORT
219
+
207
220
  timestamp
208
221
  params = @query[1..-1].split( '&' ).sort.join( '&' )
209
222
 
@@ -225,15 +238,32 @@ module Amazon
225
238
 
226
239
  params << '&Signature=%s' % [ signature ]
227
240
  @query = '?' + params
241
+
242
+ true
228
243
  end
229
244
 
230
245
 
231
- # Perform a search of the AWS database. _operation_ is one of the
232
- # objects subclassed from _Operation_, such as _ItemSearch_,
233
- # _ItemLookup_, etc. It may also be a _MultipleOperation_ object.
246
+ # Perform a search of the AWS database, returning an AWSObject.
247
+ #
248
+ # _operation_ is an object of a subclass of _Operation_, such as
249
+ # _ItemSearch_, _ItemLookup_, etc. It may also be a _MultipleOperation_
250
+ # object.
251
+ #
252
+ # _response_group_, if supplied, is a set of one or more response
253
+ # groups to use in combination with _operation_ for the purpose of
254
+ # determining which data sets AWS should return.
255
+ #
256
+ # If _response_group_ is *nil*, Ruby/AWS will instead use the response
257
+ # groups specified by the _@response_group_ attribute of _operation_.
258
+ # That is now the preferred way of specifying response groups to use
259
+ # with a given operation. The _response_group_ parameter may later be
260
+ # removed from this method altogether.
234
261
  #
235
- # _response_group_ will apply to all both operations contained in
236
- # _operation_, if _operation_ is a _MultipleOperation_ object.
262
+ # If _response_group_ is given, it will apply to all sub-operations of
263
+ # _operation_, if _operation_ is of class MultipleOperation. To use a
264
+ # different set of response groups for each sub-operation, you should
265
+ # assign to the _@response_group_ attribute of each of them before
266
+ # instantiating a MultipleOperation to combine them.
237
267
  #
238
268
  # _nr_pages_ is the number of results pages to return. It defaults to
239
269
  # <b>1</b>. If a higher number is given, pages 1 to _nr_pages_ will be
@@ -243,17 +273,23 @@ module Amazon
243
273
  # The maximum page number that can be returned for each type of
244
274
  # operation is documented in the AWS Developer's Guide:
245
275
  #
246
- # http://docs.amazonwebservices.com/AWSECommerceService/2009-01-06/DG/index.html?MaximumNumberofPages.html
276
+ # http://docs.amazonwebservices.com/AWSECommerceService/2009-03-31/DG/index.html?MaximumNumberofPages.html
247
277
  #
248
278
  # Note that _ItemLookup_ operations can use three separate pagination
249
279
  # parameters. Ruby/AWS, however, uses _OfferPage_ for the purposes of
250
280
  # returning multiple pages.
251
281
  #
252
282
  # If operation is of class _MultipleOperation_, the operations
253
- # combined within will return only the first page, regardless of
283
+ # specified within will return only the first page, regardless of
254
284
  # whether a higher number of pages is requested.
255
285
  #
256
- def search(operation, response_group, nr_pages=1)
286
+ # If a block is passed to this method, each successive page of results
287
+ # will be yielded to the block.
288
+ #
289
+ def search(operation, response_group=nil, nr_pages=1)
290
+ response_group ||=
291
+ operation.response_group || ResponseGroup.new( :Large )
292
+
257
293
  parameters = Amazon::AWS::SERVICE.
258
294
  merge( { 'AWSAccessKeyId' => @key_id,
259
295
  'AssociateTag' => @tag } ).
@@ -267,6 +303,11 @@ module Amazon
267
303
 
268
304
  @query = Amazon::AWS.assemble_query( parameters, @encoding )
269
305
  page = Amazon::AWS.get_page( self )
306
+
307
+ # Ruby 1.9 needs to know that the page is UTF-8, not ASCII-8BIT.
308
+ #
309
+ page.force_encoding( 'utf-8' ) if RUBY_VERSION >= '1.9.0'
310
+
270
311
  doc = Document.new( page )
271
312
 
272
313
  # Some errors occur at the very top level of the XML. For example,
@@ -369,6 +410,11 @@ module Amazon
369
410
  parameters.merge( { page_parameter => page_nr } ),
370
411
  @encoding)
371
412
  page = Amazon::AWS.get_page( self )
413
+
414
+ # Ruby 1.9 needs to know that the page is UTF-8, not ASCII-8BIT.
415
+ #
416
+ page.force_encoding( 'utf-8' ) if RUBY_VERSION >= '1.9.0'
417
+
372
418
  doc = Document.new( page )
373
419
 
374
420
  # Check for errors.
@@ -1,4 +1,4 @@
1
- # $Id: setup.rb,v 1.4 2009/05/25 23:35:54 ianmacd Exp $
1
+ # $Id: setup.rb,v 1.5 2009/06/14 00:28:48 ianmacd Exp $
2
2
  #
3
3
 
4
4
  # Attempt to load Ruby/AWS using RubyGems.
@@ -27,6 +27,8 @@ class AWSTest < Test::Unit::TestCase
27
27
  @req.encoding = 'utf-8'
28
28
  end
29
29
 
30
- undef_method :default_test
30
+ # The default_test method needs to be removed before Ruby 1.9.0.
31
+ #
32
+ undef_method :default_test if method_defined? :default_test
31
33
 
32
34
  end
@@ -1,4 +1,4 @@
1
- # $Id: tc_aws.rb,v 1.11 2008/10/02 21:33:58 ianmacd Exp $
1
+ # $Id: tc_aws.rb,v 1.12 2009/06/14 00:29:28 ianmacd Exp $
2
2
  #
3
3
 
4
4
  require 'test/unit'
@@ -13,7 +13,7 @@ class TestAWSBasics < AWSTest
13
13
  CACHE_PATH = File.join( Dir.tmpdir, 'aws_cache' )
14
14
 
15
15
  def test_version
16
- v = '1.8.6'
16
+ v = '1.8.7'
17
17
  assert( RUBY_VERSION >= v, "Ruby version is lower than #{v}." )
18
18
  end
19
19
 
@@ -0,0 +1,62 @@
1
+ # $Id: tc_browse_node_lookup.rb,v 1.2 2009/06/02 00:39:43 ianmacd Exp $
2
+ #
3
+
4
+ require 'test/unit'
5
+ require './setup'
6
+
7
+ class TestBrowseNodeLookup < AWSTest
8
+
9
+ def test_browse_node_lookup
10
+
11
+ bnl = BrowseNodeLookup.new( 694212 )
12
+ rg = ResponseGroup.new( :BrowseNodeInfo )
13
+
14
+ response = @req.search( bnl, rg )
15
+
16
+ results = response.kernel
17
+
18
+ # Ensure we got some actual results back.
19
+ #
20
+ assert( results.size > 0 )
21
+
22
+ end
23
+
24
+ def test_browse_node_lookup_no_response_group
25
+
26
+ bnl = BrowseNodeLookup.new( 694212 )
27
+ bnl.response_group = ResponseGroup.new( :BrowseNodeInfo )
28
+ response = @req.search( bnl, nil )
29
+
30
+ results = response.kernel
31
+
32
+ # Ensure we got more than 10 results back.
33
+ #
34
+ assert( results.size > 0 )
35
+
36
+ end
37
+
38
+ def test_browse_node_lookup_class_method
39
+
40
+ response = Amazon::AWS.browse_node_lookup( 694212 )
41
+
42
+ results = response.kernel
43
+
44
+ # Ensure we got some actual results back.
45
+ #
46
+ assert( results.size > 0 )
47
+
48
+ end
49
+
50
+ def test_browse_node_lookup_class_method_block
51
+
52
+ Amazon::AWS.browse_node_lookup( '694212' ) do |r|
53
+
54
+ results = r.kernel
55
+
56
+ # Ensure we got some actual results back.
57
+ #
58
+ assert( results.size > 0 )
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,64 @@
1
+ # $Id: tc_customer_content_lookup.rb,v 1.1 2009/06/02 00:29:18 ianmacd Exp $
2
+ #
3
+
4
+ require 'test/unit'
5
+ require './setup'
6
+
7
+ class TestCustomerContentLookup < AWSTest
8
+
9
+ def test_customer_content_lookup
10
+
11
+ @req.locale = 'us'
12
+ ccl = CustomerContentLookup.new( 'AJDWXANG1SYZP' )
13
+ rg = ResponseGroup.new( :CustomerReviews )
14
+
15
+ response = @req.search( ccl, rg )
16
+
17
+ review = response.customer_content_lookup_response.customers.customer.
18
+ customer_reviews.review[0]
19
+
20
+ # Ensure we got the right review.
21
+ #
22
+ assert_equal( 3746, review.content[0].size )
23
+
24
+ end
25
+
26
+ def test_customer_content_lookup_no_response_group
27
+
28
+ @req.locale = 'us'
29
+ ccl = CustomerContentLookup.new( 'AJDWXANG1SYZP' )
30
+ ccl.response_group = ResponseGroup.new( :CustomerReviews )
31
+ response = @req.search( ccl, nil )
32
+
33
+ review = response.customer_content_lookup_response.customers.customer.
34
+ customer_reviews.review[0]
35
+
36
+ # Ensure we got the right review.
37
+ #
38
+ assert_equal( 3746, review.content[0].size )
39
+
40
+ end
41
+
42
+ def test_customer_content_lookup_class_method
43
+
44
+ response = Amazon::AWS.customer_content_lookup( 'AA5QZU6TJQXEN' )
45
+
46
+ nickname = response.customer_content_lookup_response.customers.customer.
47
+ nickname
48
+
49
+ assert_equal( 'jimwood43', nickname )
50
+
51
+ end
52
+
53
+ def test_item_search_class_method_block
54
+
55
+ Amazon::AWS.customer_content_lookup( 'AA5QZU6TJQXEN' ) do |r|
56
+
57
+ nickname = r.customer_content_lookup_response.customers.customer.nickname
58
+
59
+ assert_equal( 'jimwood43', nickname )
60
+
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,60 @@
1
+ # $Id: tc_help.rb,v 1.2 2009/06/02 00:39:23 ianmacd Exp $
2
+ #
3
+
4
+ require 'test/unit'
5
+ require './setup'
6
+
7
+ class TestHelp < AWSTest
8
+
9
+ def test_help
10
+
11
+ h = Help.new( 'ResponseGroup', 'Large' )
12
+ rg = ResponseGroup.new( 'Help' )
13
+ response = @req.search( h, rg )
14
+
15
+ # Get a list of valid operations for the Large response group.
16
+ #
17
+ results = response.help_response[0].information.response_group_information.
18
+ valid_operations.operation
19
+
20
+ # Ensure we got some actual results back.
21
+ #
22
+ assert( results.size > 0 )
23
+
24
+ end
25
+
26
+ def test_help_no_response_group
27
+
28
+ h = Help.new( 'ResponseGroup', 'Large' )
29
+ h.response_group = ResponseGroup.new( 'Help' )
30
+ response = @req.search( h, nil )
31
+
32
+ # Get a list of valid operations for the Large response group.
33
+ #
34
+ results = response.help_response[0].information.response_group_information.
35
+ valid_operations.operation
36
+
37
+ # Ensure we got some actual results back.
38
+ #
39
+ assert( results.size > 0 )
40
+
41
+ end
42
+
43
+ def test_help_class_method
44
+
45
+ response = Amazon::AWS.help( 'ResponseGroup', 'Large' )
46
+
47
+ # With no response group, Large will be tried. The resulting exception
48
+ # will be rescued and the text of the message returned by AWS will be used
49
+ # to determine a response group that will work.
50
+ #
51
+ results = response.help_response[0].information.response_group_information.
52
+ valid_operations.operation
53
+
54
+ # Ensure we got some actual results back.
55
+ #
56
+ assert( results.size > 0 )
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,60 @@
1
+ # $Id: tc_item_lookup.rb,v 1.2 2009/05/30 11:11:27 ianmacd Exp $
2
+ #
3
+
4
+ require 'test/unit'
5
+ require './setup'
6
+
7
+ class TestItemLookup < AWSTest
8
+
9
+ def test_item_lookup
10
+
11
+ is = ItemLookup.new( 'ASIN', { 'ItemId' => 'B000AE4QEC' } )
12
+ response = @req.search( is, @rg )
13
+
14
+ results = response.kernel
15
+
16
+ # Ensure we got some actual results back.
17
+ #
18
+ assert( results.size > 0 )
19
+
20
+ end
21
+
22
+ def test_item_lookup_no_response_group
23
+
24
+ is = ItemLookup.new( 'ASIN', { 'ItemId' => 'B000AE4QEC' } )
25
+ is.response_group = ResponseGroup.new( :Small )
26
+ response = @req.search( is, nil )
27
+
28
+ results = response.kernel
29
+
30
+ # Ensure we got more than 10 results back.
31
+ #
32
+ assert( results.size > 0 )
33
+
34
+ end
35
+
36
+ def test_item_lookup_class_method
37
+
38
+ response = Amazon::AWS.item_lookup( 'ASIN', { 'ItemId' => 'B000AE4QEC' } )
39
+
40
+ results = response.kernel
41
+
42
+ # Ensure we got some actual results back.
43
+ #
44
+ assert( results.size > 0 )
45
+
46
+ end
47
+
48
+ def test_item_search_class_method_block
49
+
50
+ Amazon::AWS.item_lookup( 'ASIN', { 'ItemId' => 'B000AE4QEC' } ) do |r|
51
+
52
+ results = r.kernel
53
+
54
+ # Ensure we got some actual results back.
55
+ #
56
+ assert( results.size > 0 )
57
+ end
58
+ end
59
+
60
+ end
@@ -1,5 +1,10 @@
1
- # $Id: tc_item_search.rb,v 1.3 2009/05/26 16:18:14 ianmacd Exp $
1
+ # encoding: ASCII-8BIT
2
2
  #
3
+ # $Id: tc_item_search.rb,v 1.6 2009/06/15 10:18:07 ianmacd Exp $
4
+ #
5
+ # The encoding at the top of this file is necessary for Ruby 1.9, which will
6
+ # otherwise choke with 'invalid multibyte char (US-ASCII)' when it reads the
7
+ # ISO-8859-1 encoded accented 'e' in the test_item_search_iso_8859_15 method.
3
8
 
4
9
  require 'test/unit'
5
10
  require './setup'
@@ -12,7 +17,9 @@ class TestItemSearch < AWSTest
12
17
  # ISO-8859-15, a.k.a. Latin-15.
13
18
  #
14
19
  @req.encoding = 'iso-8859-15'
15
- is = ItemSearch.new( 'Books', { 'Title' => 'Caf�' } )
20
+
21
+ str = 'Caf�'
22
+ is = ItemSearch.new( 'Books', { 'Title' => str } )
16
23
  response = @req.search( is, @rg )
17
24
 
18
25
  results = response.kernel
@@ -28,7 +35,9 @@ class TestItemSearch < AWSTest
28
35
  # Manually set UTF-8 encoding.
29
36
  #
30
37
  @req.encoding = 'utf-8'
31
- is = ItemSearch.new( 'Books', { 'Title' => 'Café' } )
38
+
39
+ str = 'Café'
40
+ is = ItemSearch.new( 'Books', { 'Title' => str } )
32
41
  response = @req.search( is, @rg )
33
42
 
34
43
  results = response.kernel
@@ -41,13 +50,28 @@ class TestItemSearch < AWSTest
41
50
 
42
51
  def test_item_search_multiple_pages
43
52
 
53
+ @req.encoding = 'utf-8'
44
54
  is = ItemSearch.new( 'Books', { 'Title' => 'programming' } )
45
55
  responses = @req.search( is, @rg, 5 )
46
56
 
47
57
  results = []
48
- responses.each do |response|
49
- results += response.kernel
50
- end
58
+ responses.each { |response| results += response.kernel }
59
+
60
+ # Ensure we got more than 10 results back.
61
+ #
62
+ assert( results.size > 10 )
63
+
64
+ end
65
+
66
+ def test_item_search_no_response_group
67
+
68
+ @req.encoding = 'utf-8'
69
+ is = ItemSearch.new( 'Books', { 'Title' => 'programming' } )
70
+ is.response_group = ResponseGroup.new( :Small )
71
+ responses = @req.search( is, nil, 5 )
72
+
73
+ results = []
74
+ responses.each { |response| results += response.kernel }
51
75
 
52
76
  # Ensure we got more than 10 results back.
53
77
  #
@@ -55,4 +79,28 @@ class TestItemSearch < AWSTest
55
79
 
56
80
  end
57
81
 
82
+ def test_item_search_class_method
83
+
84
+ response = Amazon::AWS.item_search( 'Books', { 'Title' => 'programming' } )
85
+
86
+ results = response.kernel
87
+
88
+ # Ensure we got some actual results back.
89
+ #
90
+ assert( results.size > 0 )
91
+
92
+ end
93
+
94
+ def test_item_search_class_method_block
95
+
96
+ Amazon::AWS.item_search( 'Books', { 'Title' => 'programming' } ) do |r|
97
+
98
+ results = r.kernel
99
+
100
+ # Ensure we got some actual results back.
101
+ #
102
+ assert( results.size > 0 )
103
+ end
104
+ end
105
+
58
106
  end