comparison env/lib/python3.9/site-packages/boto/mws/connection.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 # Copyright (c) 2012-2014 Andy Davidoff http://www.disruptek.com/
2 #
3 # Permission is hereby granted, free of charge, to any person obtaining a
4 # copy of this software and associated documentation files (the
5 # "Software"), to deal in the Software without restriction, including
6 # without limitation the rights to use, copy, modify, merge, publish, dis-
7 # tribute, sublicense, and/or sell copies of the Software, and to permit
8 # persons to whom the Software is furnished to do so, subject to the fol-
9 # lowing conditions:
10 #
11 # The above copyright notice and this permission notice shall be included
12 # in all copies or substantial portions of the Software.
13 #
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 # IN THE SOFTWARE.
21 import xml.sax
22 import hashlib
23 import string
24 import collections
25 from boto.connection import AWSQueryConnection
26 from boto.exception import BotoServerError
27 import boto.mws.exception
28 import boto.mws.response
29 from boto.handler import XmlHandler
30 from boto.compat import filter, map, six, encodebytes
31
32 __all__ = ['MWSConnection']
33
34 api_version_path = {
35 'Feeds': ('2009-01-01', 'Merchant', '/'),
36 'Reports': ('2009-01-01', 'Merchant', '/'),
37 'Orders': ('2013-09-01', 'SellerId', '/Orders/2013-09-01'),
38 'Products': ('2011-10-01', 'SellerId', '/Products/2011-10-01'),
39 'Sellers': ('2011-07-01', 'SellerId', '/Sellers/2011-07-01'),
40 'Inbound': ('2010-10-01', 'SellerId',
41 '/FulfillmentInboundShipment/2010-10-01'),
42 'Outbound': ('2010-10-01', 'SellerId',
43 '/FulfillmentOutboundShipment/2010-10-01'),
44 'Inventory': ('2010-10-01', 'SellerId',
45 '/FulfillmentInventory/2010-10-01'),
46 'Recommendations': ('2013-04-01', 'SellerId',
47 '/Recommendations/2013-04-01'),
48 'CustomerInfo': ('2014-03-01', 'SellerId',
49 '/CustomerInformation/2014-03-01'),
50 'CartInfo': ('2014-03-01', 'SellerId',
51 '/CartInformation/2014-03-01'),
52 'Subscriptions': ('2013-07-01', 'SellerId',
53 '/Subscriptions/2013-07-01'),
54 'OffAmazonPayments': ('2013-01-01', 'SellerId',
55 '/OffAmazonPayments/2013-01-01'),
56 }
57 content_md5 = lambda c: encodebytes(hashlib.md5(c).digest()).strip()
58 decorated_attrs = ('action', 'response', 'section',
59 'quota', 'restore', 'version')
60 api_call_map = {}
61
62
63 def add_attrs_from(func, to):
64 for attr in decorated_attrs:
65 setattr(to, attr, getattr(func, attr, None))
66 to.__wrapped__ = func
67 return to
68
69
70 def structured_lists(*fields):
71
72 def decorator(func):
73
74 def wrapper(self, *args, **kw):
75 for key, acc in [f.split('.') for f in fields]:
76 if key in kw:
77 newkey = key + '.' + acc + (acc and '.' or '')
78 for i in range(len(kw[key])):
79 kw[newkey + str(i + 1)] = kw[key][i]
80 kw.pop(key)
81 return func(self, *args, **kw)
82 wrapper.__doc__ = "{0}\nLists: {1}".format(func.__doc__,
83 ', '.join(fields))
84 return add_attrs_from(func, to=wrapper)
85 return decorator
86
87
88 def http_body(field):
89
90 def decorator(func):
91
92 def wrapper(*args, **kw):
93 if any([f not in kw for f in (field, 'content_type')]):
94 message = "{0} requires {1} and content_type arguments for " \
95 "building HTTP body".format(func.action, field)
96 raise KeyError(message)
97 kw['body'] = kw.pop(field)
98 kw['headers'] = {
99 'Content-Type': kw.pop('content_type'),
100 'Content-MD5': content_md5(kw['body']),
101 }
102 return func(*args, **kw)
103 wrapper.__doc__ = "{0}\nRequired HTTP Body: " \
104 "{1}".format(func.__doc__, field)
105 return add_attrs_from(func, to=wrapper)
106 return decorator
107
108
109 def destructure_object(value, into, prefix, members=False):
110 if isinstance(value, boto.mws.response.ResponseElement):
111 destructure_object(value.__dict__, into, prefix, members=members)
112 elif isinstance(value, collections.Mapping):
113 for name in value:
114 if name.startswith('_'):
115 continue
116 destructure_object(value[name], into, prefix + '.' + name,
117 members=members)
118 elif isinstance(value, six.string_types):
119 into[prefix] = value
120 elif isinstance(value, collections.Iterable):
121 for index, element in enumerate(value):
122 suffix = (members and '.member.' or '.') + str(index + 1)
123 destructure_object(element, into, prefix + suffix,
124 members=members)
125 elif isinstance(value, bool):
126 into[prefix] = str(value).lower()
127 else:
128 into[prefix] = value
129
130
131 def structured_objects(*fields, **kwargs):
132
133 def decorator(func):
134
135 def wrapper(*args, **kw):
136 members = kwargs.get('members', False)
137 for field in filter(lambda i: i in kw, fields):
138 destructure_object(kw.pop(field), kw, field, members=members)
139 return func(*args, **kw)
140 wrapper.__doc__ = "{0}\nElement|Iter|Map: {1}\n" \
141 "(ResponseElement or anything iterable/dict-like)" \
142 .format(func.__doc__, ', '.join(fields))
143 return add_attrs_from(func, to=wrapper)
144 return decorator
145
146
147 def requires(*groups):
148
149 def decorator(func):
150
151 def requires(*args, **kw):
152 hasgroup = lambda group: all(key in kw for key in group)
153 if 1 != len(list(filter(hasgroup, groups))):
154 message = ' OR '.join(['+'.join(g) for g in groups])
155 message = "{0} requires {1} argument(s)" \
156 "".format(func.action, message)
157 raise KeyError(message)
158 return func(*args, **kw)
159 message = ' OR '.join(['+'.join(g) for g in groups])
160 requires.__doc__ = "{0}\nRequired: {1}".format(func.__doc__,
161 message)
162 return add_attrs_from(func, to=requires)
163 return decorator
164
165
166 def exclusive(*groups):
167
168 def decorator(func):
169
170 def wrapper(*args, **kw):
171 hasgroup = lambda group: all(key in kw for key in group)
172 if len(list(filter(hasgroup, groups))) not in (0, 1):
173 message = ' OR '.join(['+'.join(g) for g in groups])
174 message = "{0} requires either {1}" \
175 "".format(func.action, message)
176 raise KeyError(message)
177 return func(*args, **kw)
178 message = ' OR '.join(['+'.join(g) for g in groups])
179 wrapper.__doc__ = "{0}\nEither: {1}".format(func.__doc__,
180 message)
181 return add_attrs_from(func, to=wrapper)
182 return decorator
183
184
185 def dependent(field, *groups):
186
187 def decorator(func):
188
189 def wrapper(*args, **kw):
190 hasgroup = lambda group: all(key in kw for key in group)
191 if field in kw and not any(hasgroup(g) for g in groups):
192 message = ' OR '.join(['+'.join(g) for g in groups])
193 message = "{0} argument {1} requires {2}" \
194 "".format(func.action, field, message)
195 raise KeyError(message)
196 return func(*args, **kw)
197 message = ' OR '.join(['+'.join(g) for g in groups])
198 wrapper.__doc__ = "{0}\n{1} requires: {2}".format(func.__doc__,
199 field,
200 message)
201 return add_attrs_from(func, to=wrapper)
202 return decorator
203
204
205 def requires_some_of(*fields):
206
207 def decorator(func):
208
209 def requires(*args, **kw):
210 if not any(i in kw for i in fields):
211 message = "{0} requires at least one of {1} argument(s)" \
212 "".format(func.action, ', '.join(fields))
213 raise KeyError(message)
214 return func(*args, **kw)
215 requires.__doc__ = "{0}\nSome Required: {1}".format(func.__doc__,
216 ', '.join(fields))
217 return add_attrs_from(func, to=requires)
218 return decorator
219
220
221 def boolean_arguments(*fields):
222
223 def decorator(func):
224
225 def wrapper(*args, **kw):
226 for field in [f for f in fields if isinstance(kw.get(f), bool)]:
227 kw[field] = str(kw[field]).lower()
228 return func(*args, **kw)
229 wrapper.__doc__ = "{0}\nBooleans: {1}".format(func.__doc__,
230 ', '.join(fields))
231 return add_attrs_from(func, to=wrapper)
232 return decorator
233
234
235 def api_action(section, quota, restore, *api):
236
237 def decorator(func, quota=int(quota), restore=float(restore)):
238 version, accesskey, path = api_version_path[section]
239 action = ''.join(api or map(str.capitalize, func.__name__.split('_')))
240
241 def wrapper(self, *args, **kw):
242 kw.setdefault(accesskey, getattr(self, accesskey, None))
243 if kw[accesskey] is None:
244 message = "{0} requires {1} argument. Set the " \
245 "MWSConnection.{2} attribute?" \
246 "".format(action, accesskey, accesskey)
247 raise KeyError(message)
248 kw['Action'] = action
249 kw['Version'] = version
250 response = self._response_factory(action, connection=self)
251 request = dict(path=path, quota=quota, restore=restore)
252 return func(self, request, response, *args, **kw)
253 for attr in decorated_attrs:
254 setattr(wrapper, attr, locals().get(attr))
255 wrapper.__doc__ = "MWS {0}/{1} API call; quota={2} restore={3:.2f}\n" \
256 "{4}".format(action, version, quota, restore,
257 func.__doc__)
258 api_call_map[action] = func.__name__
259 return wrapper
260 return decorator
261
262
263 class MWSConnection(AWSQueryConnection):
264
265 ResponseFactory = boto.mws.response.ResponseFactory
266 ResponseErrorFactory = boto.mws.exception.ResponseErrorFactory
267
268 def __init__(self, *args, **kw):
269 kw.setdefault('host', 'mws.amazonservices.com')
270 self._sandboxed = kw.pop('sandbox', False)
271 self.Merchant = kw.pop('Merchant', None) or kw.get('SellerId')
272 self.SellerId = kw.pop('SellerId', None) or self.Merchant
273 kw = self._setup_factories(kw.pop('factory_scopes', []), **kw)
274 super(MWSConnection, self).__init__(*args, **kw)
275
276 def _setup_factories(self, extrascopes, **kw):
277 for factory, (scope, Default) in {
278 'response_factory':
279 (boto.mws.response, self.ResponseFactory),
280 'response_error_factory':
281 (boto.mws.exception, self.ResponseErrorFactory),
282 }.items():
283 if factory in kw:
284 setattr(self, '_' + factory, kw.pop(factory))
285 else:
286 scopes = extrascopes + [scope]
287 setattr(self, '_' + factory, Default(scopes=scopes))
288 return kw
289
290 def _sandboxify(self, path):
291 if not self._sandboxed:
292 return path
293 splat = path.split('/')
294 splat[-2] += '_Sandbox'
295 return '/'.join(splat)
296
297 def _required_auth_capability(self):
298 return ['mws']
299
300 def _post_request(self, request, params, parser, body='', headers=None):
301 """Make a POST request, optionally with a content body,
302 and return the response, optionally as raw text.
303 """
304 headers = headers or {}
305 path = self._sandboxify(request['path'])
306 request = self.build_base_http_request('POST', path, None, data=body,
307 params=params, headers=headers,
308 host=self.host)
309 try:
310 response = self._mexe(request, override_num_retries=None)
311 except BotoServerError as bs:
312 raise self._response_error_factory(bs.status, bs.reason, bs.body)
313 body = response.read()
314 boto.log.debug(body)
315 if not body:
316 boto.log.error('Null body %s' % body)
317 raise self._response_error_factory(response.status,
318 response.reason, body)
319 if response.status != 200:
320 boto.log.error('%s %s' % (response.status, response.reason))
321 boto.log.error('%s' % body)
322 raise self._response_error_factory(response.status,
323 response.reason, body)
324 digest = response.getheader('Content-MD5')
325 if digest is not None:
326 assert content_md5(body) == digest
327 contenttype = response.getheader('Content-Type')
328 return self._parse_response(parser, contenttype, body)
329
330 def _parse_response(self, parser, contenttype, body):
331 if not contenttype.startswith('text/xml'):
332 return body
333 handler = XmlHandler(parser, self)
334 xml.sax.parseString(body, handler)
335 return parser
336
337 def method_for(self, name):
338 """Return the MWS API method referred to in the argument.
339 The named method can be in CamelCase or underlined_lower_case.
340 This is the complement to MWSConnection.any_call.action
341 """
342 action = '_' in name and string.capwords(name, '_') or name
343 if action in api_call_map:
344 return getattr(self, api_call_map[action])
345 return None
346
347 def iter_call(self, call, *args, **kw):
348 """Pass a call name as the first argument and a generator
349 is returned for the initial response and any continuation
350 call responses made using the NextToken.
351 """
352 method = self.method_for(call)
353 assert method, 'No call named "{0}"'.format(call)
354 return self.iter_response(method(*args, **kw))
355
356 def iter_response(self, response):
357 """Pass a call's response as the initial argument and a
358 generator is returned for the initial response and any
359 continuation call responses made using the NextToken.
360 """
361 yield response
362 more = self.method_for(response._action + 'ByNextToken')
363 while more and response._result.HasNext == 'true':
364 response = more(NextToken=response._result.NextToken)
365 yield response
366
367 @requires(['FeedType'])
368 @boolean_arguments('PurgeAndReplace')
369 @http_body('FeedContent')
370 @structured_lists('MarketplaceIdList.Id')
371 @api_action('Feeds', 15, 120)
372 def submit_feed(self, request, response, headers=None, body='', **kw):
373 """Uploads a feed for processing by Amazon MWS.
374 """
375 headers = headers or {}
376 return self._post_request(request, kw, response, body=body,
377 headers=headers)
378
379 @structured_lists('FeedSubmissionIdList.Id', 'FeedTypeList.Type',
380 'FeedProcessingStatusList.Status')
381 @api_action('Feeds', 10, 45)
382 def get_feed_submission_list(self, request, response, **kw):
383 """Returns a list of all feed submissions submitted in the
384 previous 90 days.
385 """
386 return self._post_request(request, kw, response)
387
388 @requires(['NextToken'])
389 @api_action('Feeds', 0, 0)
390 def get_feed_submission_list_by_next_token(self, request, response, **kw):
391 """Returns a list of feed submissions using the NextToken parameter.
392 """
393 return self._post_request(request, kw, response)
394
395 @structured_lists('FeedTypeList.Type', 'FeedProcessingStatusList.Status')
396 @api_action('Feeds', 10, 45)
397 def get_feed_submission_count(self, request, response, **kw):
398 """Returns a count of the feeds submitted in the previous 90 days.
399 """
400 return self._post_request(request, kw, response)
401
402 @structured_lists('FeedSubmissionIdList.Id', 'FeedTypeList.Type')
403 @api_action('Feeds', 10, 45)
404 def cancel_feed_submissions(self, request, response, **kw):
405 """Cancels one or more feed submissions and returns a
406 count of the feed submissions that were canceled.
407 """
408 return self._post_request(request, kw, response)
409
410 @requires(['FeedSubmissionId'])
411 @api_action('Feeds', 15, 60)
412 def get_feed_submission_result(self, request, response, **kw):
413 """Returns the feed processing report.
414 """
415 return self._post_request(request, kw, response)
416
417 def get_service_status(self, **kw):
418 """Instruct the user on how to get service status.
419 """
420 sections = ', '.join(map(str.lower, api_version_path.keys()))
421 message = "Use {0}.get_(section)_service_status(), " \
422 "where (section) is one of the following: " \
423 "{1}".format(self.__class__.__name__, sections)
424 raise AttributeError(message)
425
426 @requires(['ReportType'])
427 @structured_lists('MarketplaceIdList.Id')
428 @boolean_arguments('ReportOptions=ShowSalesChannel')
429 @api_action('Reports', 15, 60)
430 def request_report(self, request, response, **kw):
431 """Creates a report request and submits the request to Amazon MWS.
432 """
433 return self._post_request(request, kw, response)
434
435 @structured_lists('ReportRequestIdList.Id', 'ReportTypeList.Type',
436 'ReportProcessingStatusList.Status')
437 @api_action('Reports', 10, 45)
438 def get_report_request_list(self, request, response, **kw):
439 """Returns a list of report requests that you can use to get the
440 ReportRequestId for a report.
441 """
442 return self._post_request(request, kw, response)
443
444 @requires(['NextToken'])
445 @api_action('Reports', 0, 0)
446 def get_report_request_list_by_next_token(self, request, response, **kw):
447 """Returns a list of report requests using the NextToken,
448 which was supplied by a previous request to either
449 GetReportRequestListByNextToken or GetReportRequestList, where
450 the value of HasNext was true in that previous request.
451 """
452 return self._post_request(request, kw, response)
453
454 @structured_lists('ReportTypeList.Type',
455 'ReportProcessingStatusList.Status')
456 @api_action('Reports', 10, 45)
457 def get_report_request_count(self, request, response, **kw):
458 """Returns a count of report requests that have been submitted
459 to Amazon MWS for processing.
460 """
461 return self._post_request(request, kw, response)
462
463 @api_action('Reports', 10, 45)
464 def cancel_report_requests(self, request, response, **kw):
465 """Cancel one or more report requests, returning the count of the
466 canceled report requests and the report request information.
467 """
468 return self._post_request(request, kw, response)
469
470 @boolean_arguments('Acknowledged')
471 @structured_lists('ReportRequestIdList.Id', 'ReportTypeList.Type')
472 @api_action('Reports', 10, 60)
473 def get_report_list(self, request, response, **kw):
474 """Returns a list of reports that were created in the previous
475 90 days that match the query parameters.
476 """
477 return self._post_request(request, kw, response)
478
479 @requires(['NextToken'])
480 @api_action('Reports', 0, 0)
481 def get_report_list_by_next_token(self, request, response, **kw):
482 """Returns a list of reports using the NextToken, which
483 was supplied by a previous request to either
484 GetReportListByNextToken or GetReportList, where the
485 value of HasNext was true in the previous call.
486 """
487 return self._post_request(request, kw, response)
488
489 @boolean_arguments('Acknowledged')
490 @structured_lists('ReportTypeList.Type')
491 @api_action('Reports', 10, 45)
492 def get_report_count(self, request, response, **kw):
493 """Returns a count of the reports, created in the previous 90 days,
494 with a status of _DONE_ and that are available for download.
495 """
496 return self._post_request(request, kw, response)
497
498 @requires(['ReportId'])
499 @api_action('Reports', 15, 60)
500 def get_report(self, request, response, **kw):
501 """Returns the contents of a report.
502 """
503 return self._post_request(request, kw, response)
504
505 @requires(['ReportType', 'Schedule'])
506 @api_action('Reports', 10, 45)
507 def manage_report_schedule(self, request, response, **kw):
508 """Creates, updates, or deletes a report request schedule for
509 a specified report type.
510 """
511 return self._post_request(request, kw, response)
512
513 @structured_lists('ReportTypeList.Type')
514 @api_action('Reports', 10, 45)
515 def get_report_schedule_list(self, request, response, **kw):
516 """Returns a list of order report requests that are scheduled
517 to be submitted to Amazon MWS for processing.
518 """
519 return self._post_request(request, kw, response)
520
521 @requires(['NextToken'])
522 @api_action('Reports', 0, 0)
523 def get_report_schedule_list_by_next_token(self, request, response, **kw):
524 """Returns a list of report requests using the NextToken,
525 which was supplied by a previous request to either
526 GetReportScheduleListByNextToken or GetReportScheduleList,
527 where the value of HasNext was true in that previous request.
528 """
529 return self._post_request(request, kw, response)
530
531 @structured_lists('ReportTypeList.Type')
532 @api_action('Reports', 10, 45)
533 def get_report_schedule_count(self, request, response, **kw):
534 """Returns a count of order report requests that are scheduled
535 to be submitted to Amazon MWS.
536 """
537 return self._post_request(request, kw, response)
538
539 @requires(['ReportIdList'])
540 @boolean_arguments('Acknowledged')
541 @structured_lists('ReportIdList.Id')
542 @api_action('Reports', 10, 45)
543 def update_report_acknowledgements(self, request, response, **kw):
544 """Updates the acknowledged status of one or more reports.
545 """
546 return self._post_request(request, kw, response)
547
548 @requires(['ShipFromAddress', 'InboundShipmentPlanRequestItems'])
549 @structured_objects('ShipFromAddress', 'InboundShipmentPlanRequestItems')
550 @api_action('Inbound', 30, 0.5)
551 def create_inbound_shipment_plan(self, request, response, **kw):
552 """Returns the information required to create an inbound shipment.
553 """
554 return self._post_request(request, kw, response)
555
556 @requires(['ShipmentId', 'InboundShipmentHeader', 'InboundShipmentItems'])
557 @structured_objects('InboundShipmentHeader', 'InboundShipmentItems')
558 @api_action('Inbound', 30, 0.5)
559 def create_inbound_shipment(self, request, response, **kw):
560 """Creates an inbound shipment.
561 """
562 return self._post_request(request, kw, response)
563
564 @requires(['ShipmentId'])
565 @structured_objects('InboundShipmentHeader', 'InboundShipmentItems')
566 @api_action('Inbound', 30, 0.5)
567 def update_inbound_shipment(self, request, response, **kw):
568 """Updates an existing inbound shipment. Amazon documentation
569 is ambiguous as to whether the InboundShipmentHeader and
570 InboundShipmentItems arguments are required.
571 """
572 return self._post_request(request, kw, response)
573
574 @requires_some_of('ShipmentIdList', 'ShipmentStatusList')
575 @structured_lists('ShipmentIdList.Id', 'ShipmentStatusList.Status')
576 @api_action('Inbound', 30, 0.5)
577 def list_inbound_shipments(self, request, response, **kw):
578 """Returns a list of inbound shipments based on criteria that
579 you specify.
580 """
581 return self._post_request(request, kw, response)
582
583 @requires(['NextToken'])
584 @api_action('Inbound', 30, 0.5)
585 def list_inbound_shipments_by_next_token(self, request, response, **kw):
586 """Returns the next page of inbound shipments using the NextToken
587 parameter.
588 """
589 return self._post_request(request, kw, response)
590
591 @requires(['ShipmentId'], ['LastUpdatedAfter', 'LastUpdatedBefore'])
592 @api_action('Inbound', 30, 0.5)
593 def list_inbound_shipment_items(self, request, response, **kw):
594 """Returns a list of items in a specified inbound shipment, or a
595 list of items that were updated within a specified time frame.
596 """
597 return self._post_request(request, kw, response)
598
599 @requires(['NextToken'])
600 @api_action('Inbound', 30, 0.5)
601 def list_inbound_shipment_items_by_next_token(self, request, response, **kw):
602 """Returns the next page of inbound shipment items using the
603 NextToken parameter.
604 """
605 return self._post_request(request, kw, response)
606
607 @api_action('Inbound', 2, 300, 'GetServiceStatus')
608 def get_inbound_service_status(self, request, response, **kw):
609 """Returns the operational status of the Fulfillment Inbound
610 Shipment API section.
611 """
612 return self._post_request(request, kw, response)
613
614 @requires(['SellerSkus'], ['QueryStartDateTime'])
615 @structured_lists('SellerSkus.member')
616 @api_action('Inventory', 30, 0.5)
617 def list_inventory_supply(self, request, response, **kw):
618 """Returns information about the availability of a seller's
619 inventory.
620 """
621 return self._post_request(request, kw, response)
622
623 @requires(['NextToken'])
624 @api_action('Inventory', 30, 0.5)
625 def list_inventory_supply_by_next_token(self, request, response, **kw):
626 """Returns the next page of information about the availability
627 of a seller's inventory using the NextToken parameter.
628 """
629 return self._post_request(request, kw, response)
630
631 @api_action('Inventory', 2, 300, 'GetServiceStatus')
632 def get_inventory_service_status(self, request, response, **kw):
633 """Returns the operational status of the Fulfillment Inventory
634 API section.
635 """
636 return self._post_request(request, kw, response)
637
638 @requires(['PackageNumber'])
639 @api_action('Outbound', 30, 0.5)
640 def get_package_tracking_details(self, request, response, **kw):
641 """Returns delivery tracking information for a package in
642 an outbound shipment for a Multi-Channel Fulfillment order.
643 """
644 return self._post_request(request, kw, response)
645
646 @requires(['Address', 'Items'])
647 @structured_objects('Address', 'Items')
648 @api_action('Outbound', 30, 0.5)
649 def get_fulfillment_preview(self, request, response, **kw):
650 """Returns a list of fulfillment order previews based on items
651 and shipping speed categories that you specify.
652 """
653 return self._post_request(request, kw, response)
654
655 @requires(['SellerFulfillmentOrderId', 'DisplayableOrderId',
656 'ShippingSpeedCategory', 'DisplayableOrderDateTime',
657 'DestinationAddress', 'DisplayableOrderComment',
658 'Items'])
659 @structured_objects('DestinationAddress', 'Items')
660 @api_action('Outbound', 30, 0.5)
661 def create_fulfillment_order(self, request, response, **kw):
662 """Requests that Amazon ship items from the seller's inventory
663 to a destination address.
664 """
665 return self._post_request(request, kw, response)
666
667 @requires(['SellerFulfillmentOrderId'])
668 @api_action('Outbound', 30, 0.5)
669 def get_fulfillment_order(self, request, response, **kw):
670 """Returns a fulfillment order based on a specified
671 SellerFulfillmentOrderId.
672 """
673 return self._post_request(request, kw, response)
674
675 @api_action('Outbound', 30, 0.5)
676 def list_all_fulfillment_orders(self, request, response, **kw):
677 """Returns a list of fulfillment orders fulfilled after (or
678 at) a specified date or by fulfillment method.
679 """
680 return self._post_request(request, kw, response)
681
682 @requires(['NextToken'])
683 @api_action('Outbound', 30, 0.5)
684 def list_all_fulfillment_orders_by_next_token(self, request, response, **kw):
685 """Returns the next page of inbound shipment items using the
686 NextToken parameter.
687 """
688 return self._post_request(request, kw, response)
689
690 @requires(['SellerFulfillmentOrderId'])
691 @api_action('Outbound', 30, 0.5)
692 def cancel_fulfillment_order(self, request, response, **kw):
693 """Requests that Amazon stop attempting to fulfill an existing
694 fulfillment order.
695 """
696 return self._post_request(request, kw, response)
697
698 @api_action('Outbound', 2, 300, 'GetServiceStatus')
699 def get_outbound_service_status(self, request, response, **kw):
700 """Returns the operational status of the Fulfillment Outbound
701 API section.
702 """
703 return self._post_request(request, kw, response)
704
705 @requires(['CreatedAfter'], ['LastUpdatedAfter'])
706 @requires(['MarketplaceId'])
707 @exclusive(['CreatedAfter'], ['LastUpdatedAfter'])
708 @dependent('CreatedBefore', ['CreatedAfter'])
709 @exclusive(['LastUpdatedAfter'], ['BuyerEmail'], ['SellerOrderId'])
710 @dependent('LastUpdatedBefore', ['LastUpdatedAfter'])
711 @exclusive(['CreatedAfter'], ['LastUpdatedBefore'])
712 @structured_objects('OrderTotal', 'ShippingAddress',
713 'PaymentExecutionDetail')
714 @structured_lists('MarketplaceId.Id', 'OrderStatus.Status',
715 'FulfillmentChannel.Channel', 'PaymentMethod.')
716 @api_action('Orders', 6, 60)
717 def list_orders(self, request, response, **kw):
718 """Returns a list of orders created or updated during a time
719 frame that you specify.
720 """
721 toggle = set(('FulfillmentChannel.Channel.1',
722 'OrderStatus.Status.1', 'PaymentMethod.1',
723 'LastUpdatedAfter', 'LastUpdatedBefore'))
724 for do, dont in {
725 'BuyerEmail': toggle.union(['SellerOrderId']),
726 'SellerOrderId': toggle.union(['BuyerEmail']),
727 }.items():
728 if do in kw and any(i in dont for i in kw):
729 message = "Don't include {0} when specifying " \
730 "{1}".format(' or '.join(dont), do)
731 raise AssertionError(message)
732 return self._post_request(request, kw, response)
733
734 @requires(['NextToken'])
735 @api_action('Orders', 6, 60)
736 def list_orders_by_next_token(self, request, response, **kw):
737 """Returns the next page of orders using the NextToken value
738 that was returned by your previous request to either
739 ListOrders or ListOrdersByNextToken.
740 """
741 return self._post_request(request, kw, response)
742
743 @requires(['AmazonOrderId'])
744 @structured_lists('AmazonOrderId.Id')
745 @api_action('Orders', 6, 60)
746 def get_order(self, request, response, **kw):
747 """Returns an order for each AmazonOrderId that you specify.
748 """
749 return self._post_request(request, kw, response)
750
751 @requires(['AmazonOrderId'])
752 @api_action('Orders', 30, 2)
753 def list_order_items(self, request, response, **kw):
754 """Returns order item information for an AmazonOrderId that
755 you specify.
756 """
757 return self._post_request(request, kw, response)
758
759 @requires(['NextToken'])
760 @api_action('Orders', 30, 2)
761 def list_order_items_by_next_token(self, request, response, **kw):
762 """Returns the next page of order items using the NextToken
763 value that was returned by your previous request to either
764 ListOrderItems or ListOrderItemsByNextToken.
765 """
766 return self._post_request(request, kw, response)
767
768 @api_action('Orders', 2, 300, 'GetServiceStatus')
769 def get_orders_service_status(self, request, response, **kw):
770 """Returns the operational status of the Orders API section.
771 """
772 return self._post_request(request, kw, response)
773
774 @requires(['MarketplaceId', 'Query'])
775 @api_action('Products', 20, 20)
776 def list_matching_products(self, request, response, **kw):
777 """Returns a list of products and their attributes, ordered
778 by relevancy, based on a search query that you specify.
779 """
780 return self._post_request(request, kw, response)
781
782 @requires(['MarketplaceId', 'ASINList'])
783 @structured_lists('ASINList.ASIN')
784 @api_action('Products', 20, 20)
785 def get_matching_product(self, request, response, **kw):
786 """Returns a list of products and their attributes, based on
787 a list of ASIN values that you specify.
788 """
789 return self._post_request(request, kw, response)
790
791 @requires(['MarketplaceId', 'IdType', 'IdList'])
792 @structured_lists('IdList.Id')
793 @api_action('Products', 20, 20)
794 def get_matching_product_for_id(self, request, response, **kw):
795 """Returns a list of products and their attributes, based on
796 a list of Product IDs that you specify.
797 """
798 return self._post_request(request, kw, response)
799
800 @requires(['MarketplaceId', 'SellerSKUList'])
801 @structured_lists('SellerSKUList.SellerSKU')
802 @api_action('Products', 20, 10, 'GetCompetitivePricingForSKU')
803 def get_competitive_pricing_for_sku(self, request, response, **kw):
804 """Returns the current competitive pricing of a product,
805 based on the SellerSKUs and MarketplaceId that you specify.
806 """
807 return self._post_request(request, kw, response)
808
809 @requires(['MarketplaceId', 'ASINList'])
810 @structured_lists('ASINList.ASIN')
811 @api_action('Products', 20, 10, 'GetCompetitivePricingForASIN')
812 def get_competitive_pricing_for_asin(self, request, response, **kw):
813 """Returns the current competitive pricing of a product,
814 based on the ASINs and MarketplaceId that you specify.
815 """
816 return self._post_request(request, kw, response)
817
818 @requires(['MarketplaceId', 'SellerSKUList'])
819 @structured_lists('SellerSKUList.SellerSKU')
820 @api_action('Products', 20, 5, 'GetLowestOfferListingsForSKU')
821 def get_lowest_offer_listings_for_sku(self, request, response, **kw):
822 """Returns the lowest price offer listings for a specific
823 product by item condition and SellerSKUs.
824 """
825 return self._post_request(request, kw, response)
826
827 @requires(['MarketplaceId', 'ASINList'])
828 @structured_lists('ASINList.ASIN')
829 @api_action('Products', 20, 5, 'GetLowestOfferListingsForASIN')
830 def get_lowest_offer_listings_for_asin(self, request, response, **kw):
831 """Returns the lowest price offer listings for a specific
832 product by item condition and ASINs.
833 """
834 return self._post_request(request, kw, response)
835
836 @requires(['MarketplaceId', 'SellerSKU'])
837 @api_action('Products', 20, 20, 'GetProductCategoriesForSKU')
838 def get_product_categories_for_sku(self, request, response, **kw):
839 """Returns the product categories that a SellerSKU belongs to.
840 """
841 return self._post_request(request, kw, response)
842
843 @requires(['MarketplaceId', 'ASIN'])
844 @api_action('Products', 20, 20, 'GetProductCategoriesForASIN')
845 def get_product_categories_for_asin(self, request, response, **kw):
846 """Returns the product categories that an ASIN belongs to.
847 """
848 return self._post_request(request, kw, response)
849
850 @api_action('Products', 2, 300, 'GetServiceStatus')
851 def get_products_service_status(self, request, response, **kw):
852 """Returns the operational status of the Products API section.
853 """
854 return self._post_request(request, kw, response)
855
856 @requires(['MarketplaceId', 'SellerSKUList'])
857 @structured_lists('SellerSKUList.SellerSKU')
858 @api_action('Products', 20, 10, 'GetMyPriceForSKU')
859 def get_my_price_for_sku(self, request, response, **kw):
860 """Returns pricing information for your own offer listings, based on SellerSKU.
861 """
862 return self._post_request(request, kw, response)
863
864 @requires(['MarketplaceId', 'ASINList'])
865 @structured_lists('ASINList.ASIN')
866 @api_action('Products', 20, 10, 'GetMyPriceForASIN')
867 def get_my_price_for_asin(self, request, response, **kw):
868 """Returns pricing information for your own offer listings, based on ASIN.
869 """
870 return self._post_request(request, kw, response)
871
872 @api_action('Sellers', 15, 60)
873 def list_marketplace_participations(self, request, response, **kw):
874 """Returns a list of marketplaces that the seller submitting
875 the request can sell in, and a list of participations that
876 include seller-specific information in that marketplace.
877 """
878 return self._post_request(request, kw, response)
879
880 @requires(['NextToken'])
881 @api_action('Sellers', 15, 60)
882 def list_marketplace_participations_by_next_token(self, request, response,
883 **kw):
884 """Returns the next page of marketplaces and participations
885 using the NextToken value that was returned by your
886 previous request to either ListMarketplaceParticipations
887 or ListMarketplaceParticipationsByNextToken.
888 """
889 return self._post_request(request, kw, response)
890
891 @requires(['MarketplaceId'])
892 @api_action('Recommendations', 5, 2)
893 def get_last_updated_time_for_recommendations(self, request, response,
894 **kw):
895 """Checks whether there are active recommendations for each category
896 for the given marketplace, and if there are, returns the time when
897 recommendations were last updated for each category.
898 """
899 return self._post_request(request, kw, response)
900
901 @requires(['MarketplaceId'])
902 @structured_lists('CategoryQueryList.CategoryQuery')
903 @api_action('Recommendations', 5, 2)
904 def list_recommendations(self, request, response, **kw):
905 """Returns your active recommendations for a specific category or for
906 all categories for a specific marketplace.
907 """
908 return self._post_request(request, kw, response)
909
910 @requires(['NextToken'])
911 @api_action('Recommendations', 5, 2)
912 def list_recommendations_by_next_token(self, request, response, **kw):
913 """Returns the next page of recommendations using the NextToken
914 parameter.
915 """
916 return self._post_request(request, kw, response)
917
918 @api_action('Recommendations', 2, 300, 'GetServiceStatus')
919 def get_recommendations_service_status(self, request, response, **kw):
920 """Returns the operational status of the Recommendations API section.
921 """
922 return self._post_request(request, kw, response)
923
924 @api_action('CustomerInfo', 15, 12)
925 def list_customers(self, request, response, **kw):
926 """Returns a list of customer accounts based on search criteria that
927 you specify.
928 """
929 return self._post_request(request, kw, response)
930
931 @requires(['NextToken'])
932 @api_action('CustomerInfo', 50, 3)
933 def list_customers_by_next_token(self, request, response, **kw):
934 """Returns the next page of customers using the NextToken parameter.
935 """
936 return self._post_request(request, kw, response)
937
938 @requires(['CustomerIdList'])
939 @structured_lists('CustomerIdList.CustomerId')
940 @api_action('CustomerInfo', 15, 12)
941 def get_customers_for_customer_id(self, request, response, **kw):
942 """Returns a list of customer accounts based on search criteria that
943 you specify.
944 """
945 return self._post_request(request, kw, response)
946
947 @api_action('CustomerInfo', 2, 300, 'GetServiceStatus')
948 def get_customerinfo_service_status(self, request, response, **kw):
949 """Returns the operational status of the Customer Information API
950 section.
951 """
952 return self._post_request(request, kw, response)
953
954 @requires(['DateRangeStart'])
955 @api_action('CartInfo', 15, 12)
956 def list_carts(self, request, response, **kw):
957 """Returns a list of shopping carts in your Webstore that were last
958 updated during the time range that you specify.
959 """
960 return self._post_request(request, kw, response)
961
962 @requires(['NextToken'])
963 @api_action('CartInfo', 50, 3)
964 def list_carts_by_next_token(self, request, response, **kw):
965 """Returns the next page of shopping carts using the NextToken
966 parameter.
967 """
968 return self._post_request(request, kw, response)
969
970 @requires(['CartIdList'])
971 @structured_lists('CartIdList.CartId')
972 @api_action('CartInfo', 15, 12)
973 def get_carts(self, request, response, **kw):
974 """Returns shopping carts based on the CartId values that you specify.
975 """
976 return self._post_request(request, kw, response)
977
978 @api_action('CartInfo', 2, 300, 'GetServiceStatus')
979 def get_cartinfo_service_status(self, request, response, **kw):
980 """Returns the operational status of the Cart Information API section.
981 """
982 return self._post_request(request, kw, response)
983
984 @requires(['MarketplaceId', 'Destination'])
985 @structured_objects('Destination', members=True)
986 @api_action('Subscriptions', 25, 0.5)
987 def register_destination(self, request, response, **kw):
988 """Specifies a new destination where you want to receive notifications.
989 """
990 return self._post_request(request, kw, response)
991
992 @requires(['MarketplaceId', 'Destination'])
993 @structured_objects('Destination', members=True)
994 @api_action('Subscriptions', 25, 0.5)
995 def deregister_destination(self, request, response, **kw):
996 """Removes an existing destination from the list of registered
997 destinations.
998 """
999 return self._post_request(request, kw, response)
1000
1001 @requires(['MarketplaceId'])
1002 @api_action('Subscriptions', 25, 0.5)
1003 def list_registered_destinations(self, request, response, **kw):
1004 """Lists all current destinations that you have registered.
1005 """
1006 return self._post_request(request, kw, response)
1007
1008 @requires(['MarketplaceId', 'Destination'])
1009 @structured_objects('Destination', members=True)
1010 @api_action('Subscriptions', 25, 0.5)
1011 def send_test_notification_to_destination(self, request, response, **kw):
1012 """Sends a test notification to an existing destination.
1013 """
1014 return self._post_request(request, kw, response)
1015
1016 @requires(['MarketplaceId', 'Subscription'])
1017 @structured_objects('Subscription', members=True)
1018 @api_action('Subscriptions', 25, 0.5)
1019 def create_subscription(self, request, response, **kw):
1020 """Creates a new subscription for the specified notification type
1021 and destination.
1022 """
1023 return self._post_request(request, kw, response)
1024
1025 @requires(['MarketplaceId', 'NotificationType', 'Destination'])
1026 @structured_objects('Destination', members=True)
1027 @api_action('Subscriptions', 25, 0.5)
1028 def get_subscription(self, request, response, **kw):
1029 """Gets the subscription for the specified notification type and
1030 destination.
1031 """
1032 return self._post_request(request, kw, response)
1033
1034 @requires(['MarketplaceId', 'NotificationType', 'Destination'])
1035 @structured_objects('Destination', members=True)
1036 @api_action('Subscriptions', 25, 0.5)
1037 def delete_subscription(self, request, response, **kw):
1038 """Deletes the subscription for the specified notification type and
1039 destination.
1040 """
1041 return self._post_request(request, kw, response)
1042
1043 @requires(['MarketplaceId'])
1044 @api_action('Subscriptions', 25, 0.5)
1045 def list_subscriptions(self, request, response, **kw):
1046 """Returns a list of all your current subscriptions.
1047 """
1048 return self._post_request(request, kw, response)
1049
1050 @requires(['MarketplaceId', 'Subscription'])
1051 @structured_objects('Subscription', members=True)
1052 @api_action('Subscriptions', 25, 0.5)
1053 def update_subscription(self, request, response, **kw):
1054 """Updates the subscription for the specified notification type and
1055 destination.
1056 """
1057 return self._post_request(request, kw, response)
1058
1059 @api_action('Subscriptions', 2, 300, 'GetServiceStatus')
1060 def get_subscriptions_service_status(self, request, response, **kw):
1061 """Returns the operational status of the Subscriptions API section.
1062 """
1063 return self._post_request(request, kw, response)
1064
1065 @requires(['AmazonOrderReferenceId', 'OrderReferenceAttributes'])
1066 @structured_objects('OrderReferenceAttributes')
1067 @api_action('OffAmazonPayments', 10, 1)
1068 def set_order_reference_details(self, request, response, **kw):
1069 """Sets order reference details such as the order total and a
1070 description for the order.
1071 """
1072 return self._post_request(request, kw, response)
1073
1074 @requires(['AmazonOrderReferenceId'])
1075 @api_action('OffAmazonPayments', 20, 2)
1076 def get_order_reference_details(self, request, response, **kw):
1077 """Returns details about the Order Reference object and its current
1078 state.
1079 """
1080 return self._post_request(request, kw, response)
1081
1082 @requires(['AmazonOrderReferenceId'])
1083 @api_action('OffAmazonPayments', 10, 1)
1084 def confirm_order_reference(self, request, response, **kw):
1085 """Confirms that the order reference is free of constraints and all
1086 required information has been set on the order reference.
1087 """
1088 return self._post_request(request, kw, response)
1089
1090 @requires(['AmazonOrderReferenceId'])
1091 @api_action('OffAmazonPayments', 10, 1)
1092 def cancel_order_reference(self, request, response, **kw):
1093 """Cancel an order reference; all authorizations associated with
1094 this order reference are also closed.
1095 """
1096 return self._post_request(request, kw, response)
1097
1098 @requires(['AmazonOrderReferenceId'])
1099 @api_action('OffAmazonPayments', 10, 1)
1100 def close_order_reference(self, request, response, **kw):
1101 """Confirms that an order reference has been fulfilled (fully
1102 or partially) and that you do not expect to create any new
1103 authorizations on this order reference.
1104 """
1105 return self._post_request(request, kw, response)
1106
1107 @requires(['AmazonOrderReferenceId', 'AuthorizationReferenceId',
1108 'AuthorizationAmount'])
1109 @structured_objects('AuthorizationAmount')
1110 @api_action('OffAmazonPayments', 10, 1)
1111 def authorize(self, request, response, **kw):
1112 """Reserves a specified amount against the payment method(s) stored in
1113 the order reference.
1114 """
1115 return self._post_request(request, kw, response)
1116
1117 @requires(['AmazonAuthorizationId'])
1118 @api_action('OffAmazonPayments', 20, 2)
1119 def get_authorization_details(self, request, response, **kw):
1120 """Returns the status of a particular authorization and the total
1121 amount captured on the authorization.
1122 """
1123 return self._post_request(request, kw, response)
1124
1125 @requires(['AmazonAuthorizationId', 'CaptureReferenceId', 'CaptureAmount'])
1126 @structured_objects('CaptureAmount')
1127 @api_action('OffAmazonPayments', 10, 1)
1128 def capture(self, request, response, **kw):
1129 """Captures funds from an authorized payment instrument.
1130 """
1131 return self._post_request(request, kw, response)
1132
1133 @requires(['AmazonCaptureId'])
1134 @api_action('OffAmazonPayments', 20, 2)
1135 def get_capture_details(self, request, response, **kw):
1136 """Returns the status of a particular capture and the total amount
1137 refunded on the capture.
1138 """
1139 return self._post_request(request, kw, response)
1140
1141 @requires(['AmazonAuthorizationId'])
1142 @api_action('OffAmazonPayments', 10, 1)
1143 def close_authorization(self, request, response, **kw):
1144 """Closes an authorization.
1145 """
1146 return self._post_request(request, kw, response)
1147
1148 @requires(['AmazonCaptureId', 'RefundReferenceId', 'RefundAmount'])
1149 @structured_objects('RefundAmount')
1150 @api_action('OffAmazonPayments', 10, 1)
1151 def refund(self, request, response, **kw):
1152 """Refunds a previously captured amount.
1153 """
1154 return self._post_request(request, kw, response)
1155
1156 @requires(['AmazonRefundId'])
1157 @api_action('OffAmazonPayments', 20, 2)
1158 def get_refund_details(self, request, response, **kw):
1159 """Returns the status of a particular refund.
1160 """
1161 return self._post_request(request, kw, response)
1162
1163 @api_action('OffAmazonPayments', 2, 300, 'GetServiceStatus')
1164 def get_offamazonpayments_service_status(self, request, response, **kw):
1165 """Returns the operational status of the Off-Amazon Payments API
1166 section.
1167 """
1168 return self._post_request(request, kw, response)