peddler 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -5
- data/lib/mws/feeds/client.rb +5 -3
- data/lib/mws/orders/client.rb +2 -1
- data/lib/mws/reports/client.rb +4 -4
- data/lib/peddler/client.rb +6 -1
- data/lib/peddler/flat_file_parser.rb +3 -1
- data/lib/peddler/marketplace.rb +6 -4
- data/lib/peddler/parser.rb +1 -1
- data/lib/peddler/test/vcr_matcher.rb +10 -3
- data/lib/peddler/version.rb +1 -1
- data/lib/peddler/xml_response_parser.rb +4 -3
- data/test/integration/test_feeds.rb +18 -0
- data/test/integration/test_reports.rb +9 -0
- data/test/unit/mws/test_feeds_client.rb +7 -2
- data/test/unit/peddler/test_client.rb +2 -2
- data/test/unit/peddler/test_flat_file_parser.rb +30 -1
- data/test/unit/peddler/test_parser.rb +1 -1
- data/test/vcr_cassettes/Feeds.yml +3621 -8
- data/test/vcr_cassettes/Reports.yml +544 -72
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ebc3731112b872c4fd188f5f2a670906d306deb
|
4
|
+
data.tar.gz: 6dd3f8389d2ab5837fd6a614da7f005fc74f35f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb1753e3b07215bc3749d7a49cca3441d7149b61bb1b76f024b0d938553c9a30d90129cfa785ad831b243637b6c4a32c79c1c4b1a72d24ab15b449baa0d92e61
|
7
|
+
data.tar.gz: d08981d7ee8b42ab481983ae999671619517be7d7e0df8e23c17731a62bbca01001c167943845cbcc8705e645c5527d2619f2b5aa030af4fec37625e0cc3c5ee
|
data/README.md
CHANGED
@@ -41,36 +41,38 @@ export AWS_SECRET_ACCESS_KEY=qux
|
|
41
41
|
You can now instantiate a client.
|
42
42
|
|
43
43
|
```ruby
|
44
|
-
client = MWS
|
44
|
+
client = MWS.orders
|
45
45
|
```
|
46
46
|
|
47
47
|
Alternatively, you can set some or all credentials when or after creating the client.
|
48
48
|
|
49
49
|
```ruby
|
50
|
-
client = MWS
|
50
|
+
client = MWS.orders(
|
51
51
|
primary_marketplace_id: "foo",
|
52
52
|
merchant_id: "bar",
|
53
53
|
aws_access_key_id: "baz",
|
54
54
|
aws_secret_access_key: "qux"
|
55
55
|
)
|
56
|
+
client.primary_marketplace_id = "bar"
|
56
57
|
```
|
57
58
|
|
58
59
|
If you are creating a client for another seller, pass the latter's `MWSAuthToken` to the client.
|
59
60
|
|
60
61
|
```ruby
|
62
|
+
client = MWS.orders
|
61
63
|
client.auth_token = "corge"
|
62
64
|
```
|
63
65
|
|
64
|
-
Once you have a client with valid credentials, you should be able to make requests to the API.
|
66
|
+
Once you have a client with valid credentials, you should be able to make requests to the API. Clients map operation names in a flat structure. Methods have positional arguments for required input and keyword arguments for optional parameters. Both method and argument names are underscored but otherwise identical to the names of the corresponding operations and parameters documented in the API.
|
65
67
|
|
66
|
-
Peddler
|
68
|
+
Peddler wraps successful responses in a parser that handles both XML documents and flat files.
|
67
69
|
|
68
70
|
```ruby
|
69
71
|
parser = client.get_service_status
|
70
72
|
parser.parse # will return a Hash or CSV object
|
71
73
|
```
|
72
74
|
|
73
|
-
You can swap the default parser with a purpose-built
|
75
|
+
You can swap the default parser with a purpose-built abstraction.
|
74
76
|
|
75
77
|
```ruby
|
76
78
|
MWS::Orders::Client.parser = MyParser
|
data/lib/mws/feeds/client.rb
CHANGED
@@ -27,7 +27,7 @@ module MWS
|
|
27
27
|
run
|
28
28
|
end
|
29
29
|
|
30
|
-
#
|
30
|
+
# Lists feed submissions
|
31
31
|
#
|
32
32
|
# @see http://docs.developer.amazonservices.com/en_US/feeds/Feeds_GetFeedSubmissionList.html
|
33
33
|
# @see http://docs.developer.amazonservices.com/en_US/feeds/Feeds_FeedType.html
|
@@ -49,7 +49,7 @@ module MWS
|
|
49
49
|
run
|
50
50
|
end
|
51
51
|
|
52
|
-
#
|
52
|
+
# Lists the next page of feed submissions
|
53
53
|
#
|
54
54
|
# @see http://docs.developer.amazonservices.com/en_US/feeds/Feeds_GetFeedSubmissionListByNextToken.html
|
55
55
|
# @param next_token [String]
|
@@ -80,7 +80,7 @@ module MWS
|
|
80
80
|
run
|
81
81
|
end
|
82
82
|
|
83
|
-
#
|
83
|
+
# Cancels one or more feed submissions
|
84
84
|
#
|
85
85
|
# @see http://docs.developer.amazonservices.com/en_US/feeds/Feeds_CancelFeedSubmissions.html
|
86
86
|
# @see http://docs.developer.amazonservices.com/en_US/feeds/Feeds_FeedType.html
|
@@ -93,6 +93,8 @@ module MWS
|
|
93
93
|
def cancel_feed_submissions(opts = {})
|
94
94
|
operation('CancelFeedSubmissions')
|
95
95
|
.add(opts)
|
96
|
+
.structure!('FeedSubmissionIdList', 'Id')
|
97
|
+
.structure!('FeedTypeList', 'Type')
|
96
98
|
|
97
99
|
run
|
98
100
|
end
|
data/lib/mws/orders/client.rb
CHANGED
@@ -11,7 +11,8 @@ module MWS
|
|
11
11
|
# Lists orders
|
12
12
|
#
|
13
13
|
# @note When calling this operation, you must specify a time frame using
|
14
|
-
# either created_after or last_updated_after.
|
14
|
+
# either created_after or last_updated_after. When requesting orders by
|
15
|
+
# "Unshipped" status you must also request "PartiallyShipped" orders.
|
15
16
|
# @see http://docs.developer.amazonservices.com/en_US/orders/2013-09-01/Orders_ListOrders.html
|
16
17
|
# @param opts [Hash]
|
17
18
|
# @option opts [String, #iso8601] :created_after
|
data/lib/mws/reports/client.rb
CHANGED
@@ -170,7 +170,7 @@ module MWS
|
|
170
170
|
run
|
171
171
|
end
|
172
172
|
|
173
|
-
#
|
173
|
+
# Lists scheduled reports
|
174
174
|
#
|
175
175
|
# @see http://docs.developer.amazonservices.com/en_US/reports/Reports_GetReportScheduleList.html
|
176
176
|
# @param report_type_list [*Array<String>]
|
@@ -183,7 +183,7 @@ module MWS
|
|
183
183
|
run
|
184
184
|
end
|
185
185
|
|
186
|
-
#
|
186
|
+
# Lists next page of scheduled reports
|
187
187
|
#
|
188
188
|
# @see http://docs.developer.amazonservices.com/en_US/reports/Reports_GetReportScheduleListByNextToken.html
|
189
189
|
# @raise [NotImplementedError]
|
@@ -191,7 +191,7 @@ module MWS
|
|
191
191
|
fail NotImplementedError
|
192
192
|
end
|
193
193
|
|
194
|
-
#
|
194
|
+
# Counts scheduled reports
|
195
195
|
#
|
196
196
|
# @see http://docs.developer.amazonservices.com/en_US/reports/Reports_GetReportScheduleCount.html
|
197
197
|
# @param report_type_list [Array<String>]
|
@@ -204,7 +204,7 @@ module MWS
|
|
204
204
|
run
|
205
205
|
end
|
206
206
|
|
207
|
-
#
|
207
|
+
# Updates acknowledged status of one or more reports
|
208
208
|
#
|
209
209
|
# @see http://docs.developer.amazonservices.com/en_US/reports/Reports_UpdateReportAcknowledgements.html
|
210
210
|
# @param acknowledged [Boolean]
|
data/lib/peddler/client.rb
CHANGED
@@ -133,7 +133,12 @@ module Peddler
|
|
133
133
|
|
134
134
|
# @!parse attr_writer :body
|
135
135
|
def body=(str)
|
136
|
-
|
136
|
+
if str
|
137
|
+
headers['Content-Type'] = content_type(str)
|
138
|
+
else
|
139
|
+
headers.delete('Content-Type')
|
140
|
+
end
|
141
|
+
|
137
142
|
@body = str
|
138
143
|
end
|
139
144
|
|
data/lib/peddler/marketplace.rb
CHANGED
@@ -27,15 +27,17 @@ module Peddler
|
|
27
27
|
@host ||= find_host
|
28
28
|
end
|
29
29
|
|
30
|
+
# Caveat: We use the supersets Windows-31J and CP1252 in place of Shift_JIS
|
31
|
+
# and ISO 8859-1 respectively to handle edge cases where latter will not
|
32
|
+
# support some characters. The supersets should be safe to use as drop-in
|
33
|
+
# replacements.
|
30
34
|
def encoding
|
31
35
|
if japanese?
|
32
|
-
|
33
|
-
# work but Windows-31J did when parsing a report.
|
34
|
-
'Shift_JIS'
|
36
|
+
'Windows-31J'
|
35
37
|
elsif chinese?
|
36
38
|
'UTF-16'
|
37
39
|
else
|
38
|
-
'
|
40
|
+
'CP1252'
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
data/lib/peddler/parser.rb
CHANGED
@@ -8,7 +8,7 @@ module Peddler
|
|
8
8
|
class << self
|
9
9
|
# The inevitable-seeming messiness of massaging data produced by a motley
|
10
10
|
# army of Amazon developers
|
11
|
-
def new(res, encoding
|
11
|
+
def new(res, encoding)
|
12
12
|
# Don't parse if there's no body
|
13
13
|
return res unless res.body
|
14
14
|
|
@@ -22,15 +22,22 @@ module Peddler
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def compare_uri
|
25
|
-
|
25
|
+
uri_1 = URI.parse(req_1.uri)
|
26
|
+
uri_2 = URI.parse(req_2.uri)
|
27
|
+
|
28
|
+
uri_1.host == uri_2.host &&
|
29
|
+
uri_1.path == uri_2.path &&
|
30
|
+
extract_params(uri_1.query) == extract_params(uri_2.query)
|
26
31
|
end
|
27
32
|
|
28
33
|
def compare_body
|
29
34
|
extract_params(req_1.body) == extract_params(req_2.body)
|
30
35
|
end
|
31
36
|
|
32
|
-
def extract_params(
|
33
|
-
|
37
|
+
def extract_params(string)
|
38
|
+
return {} unless string
|
39
|
+
|
40
|
+
params = ::CGI.parse(string)
|
34
41
|
TRANSIENT_PARAMS.each do |k|
|
35
42
|
params.delete(k)
|
36
43
|
end
|
data/lib/peddler/version.rb
CHANGED
@@ -10,10 +10,11 @@ module Peddler
|
|
10
10
|
private
|
11
11
|
|
12
12
|
def find_data
|
13
|
-
|
14
|
-
|
13
|
+
payload = xml.values.first
|
14
|
+
found = payload.find { |k, _| k.include?('Result') } ||
|
15
|
+
payload.find { |k, _| k == 'Message' }
|
15
16
|
|
16
|
-
|
17
|
+
found.last if found
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|
@@ -15,4 +15,22 @@ class TestFeeds < IntegrationTest
|
|
15
15
|
refute_empty res.parse
|
16
16
|
end
|
17
17
|
end
|
18
|
+
|
19
|
+
def test_submits_feeds
|
20
|
+
content = "sku\tprice\tquantity\nwidget\t\t0\n"
|
21
|
+
type = '_POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA_'
|
22
|
+
|
23
|
+
clients.each do |client|
|
24
|
+
res = client.submit_feed(content, type)
|
25
|
+
id = res.parse['FeedSubmissionInfo']['FeedSubmissionId']
|
26
|
+
refute_nil id
|
27
|
+
|
28
|
+
# Clean up
|
29
|
+
client.body = nil
|
30
|
+
client.cancel_feed_submissions(
|
31
|
+
feed_submission_id: id,
|
32
|
+
feed_type_list: type
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
18
36
|
end
|
@@ -43,4 +43,13 @@ class TestReports < IntegrationTest
|
|
43
43
|
refute_empty res.parse
|
44
44
|
end
|
45
45
|
end
|
46
|
+
|
47
|
+
def test_gets_report
|
48
|
+
clients.each do |client|
|
49
|
+
res = client.get_report_list(max_count: 1)
|
50
|
+
id = res.parse['ReportInfo']['ReportId']
|
51
|
+
res = client.get_report(id)
|
52
|
+
refute_empty res.parse || res.records_count
|
53
|
+
end
|
54
|
+
end
|
46
55
|
end
|
@@ -73,11 +73,16 @@ class TestMWSFeedsClient < MiniTest::Test
|
|
73
73
|
|
74
74
|
def test_cancels_feed_submissions
|
75
75
|
operation = {
|
76
|
-
'Action' => 'CancelFeedSubmissions'
|
76
|
+
'Action' => 'CancelFeedSubmissions',
|
77
|
+
'FeedTypeList.Type.1' => '1',
|
78
|
+
'FeedSubmissionIdList.Id.1' => '2'
|
77
79
|
}
|
78
80
|
|
79
81
|
@client.stub(:run, nil) do
|
80
|
-
@client.cancel_feed_submissions
|
82
|
+
@client.cancel_feed_submissions(
|
83
|
+
feed_type_list: '1',
|
84
|
+
feed_submission_id_list: '2'
|
85
|
+
)
|
81
86
|
end
|
82
87
|
|
83
88
|
assert_equal operation, @client.operation
|
@@ -78,7 +78,7 @@ class TestPeddlerClient < MiniTest::Test
|
|
78
78
|
@client.body = 'foo'
|
79
79
|
content_type = @client.headers.fetch('Content-Type')
|
80
80
|
|
81
|
-
assert_equal 'text/tab-separated-values; charset=
|
81
|
+
assert_equal 'text/tab-separated-values; charset=CP1252', content_type
|
82
82
|
end
|
83
83
|
|
84
84
|
def test_sets_content_type_header_for_chinese_flat_file_body
|
@@ -94,7 +94,7 @@ class TestPeddlerClient < MiniTest::Test
|
|
94
94
|
@client.body = 'foo'
|
95
95
|
content_type = @client.headers.fetch('Content-Type')
|
96
96
|
|
97
|
-
assert_equal 'text/tab-separated-values; charset=
|
97
|
+
assert_equal 'text/tab-separated-values; charset=Windows-31J', content_type
|
98
98
|
end
|
99
99
|
|
100
100
|
def test_sets_content_type_header_for_xml_body
|
@@ -41,8 +41,37 @@ class TestPeddlerFlatFileParser < MiniTest::Test
|
|
41
41
|
body.encode!('SHIFT_JIS')
|
42
42
|
body.force_encoding('ASCII-8BIT')
|
43
43
|
res = OpenStruct.new(body: body)
|
44
|
-
parser = Peddler::FlatFileParser.new(res, '
|
44
|
+
parser = Peddler::FlatFileParser.new(res, 'Windows-31J')
|
45
45
|
|
46
46
|
assert_equal 'こんにちは', parser.parse[0]['Foo']
|
47
47
|
end
|
48
|
+
|
49
|
+
def test_handles_japanese_curly_braces
|
50
|
+
body = "Foo\n〝\n"
|
51
|
+
body.encode!('Windows-31J')
|
52
|
+
body.force_encoding('ASCII-8BIT')
|
53
|
+
res = OpenStruct.new(body: body)
|
54
|
+
parser = Peddler::FlatFileParser.new(res, 'Windows-31J')
|
55
|
+
|
56
|
+
assert_equal '〝', parser.parse[0]['Foo']
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_handles_latin_1_flat_files
|
60
|
+
body = "Foo\n™\n"
|
61
|
+
body.encode!('Cp1252')
|
62
|
+
body.force_encoding('ASCII-8BIT')
|
63
|
+
res = OpenStruct.new(body: body)
|
64
|
+
parser = Peddler::FlatFileParser.new(res, 'Cp1252')
|
65
|
+
|
66
|
+
assert_equal '™', parser.parse['Foo'][0]
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_handles_undefined_characters
|
70
|
+
body = "Foo\n\xFF\n"
|
71
|
+
body.force_encoding('ASCII-8BIT')
|
72
|
+
res = OpenStruct.new(body: body)
|
73
|
+
parser = Peddler::FlatFileParser.new(res, 'ASCII-8BIT')
|
74
|
+
|
75
|
+
assert_equal '?', parser.parse['Foo'][0]
|
76
|
+
end
|
48
77
|
end
|