Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(452)

Side by Side Diff: third_party/gsutil/boto/mws/connection.py

Issue 12042069: Scripts to download files from google storage based on sha1 sums (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Removed gsutil/tests and gsutil/docs Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright (c) 2012 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 base64
24 import string
25 from boto.connection import AWSQueryConnection
26 from boto.mws.exception import ResponseErrorFactory
27 from boto.mws.response import ResponseFactory, ResponseElement
28 from boto.handler import XmlHandler
29 import boto.mws.response
30
31 __all__ = ['MWSConnection']
32
33 api_version_path = {
34 'Feeds': ('2009-01-01', 'Merchant', '/'),
35 'Reports': ('2009-01-01', 'Merchant', '/'),
36 'Orders': ('2011-01-01', 'SellerId', '/Orders/2011-01-01'),
37 'Products': ('2011-10-01', 'SellerId', '/Products/2011-10-01'),
38 'Sellers': ('2011-07-01', 'SellerId', '/Sellers/2011-07-01'),
39 'Inbound': ('2010-10-01', 'SellerId',
40 '/FulfillmentInboundShipment/2010-10-01'),
41 'Outbound': ('2010-10-01', 'SellerId',
42 '/FulfillmentOutboundShipment/2010-10-01'),
43 'Inventory': ('2010-10-01', 'SellerId',
44 '/FulfillmentInventory/2010-10-01'),
45 }
46 content_md5 = lambda c: base64.encodestring(hashlib.md5(c).digest()).strip()
47 decorated_attrs = ('action', 'response', 'section',
48 'quota', 'restore', 'version')
49
50
51 def add_attrs_from(func, to):
52 for attr in decorated_attrs:
53 setattr(to, attr, getattr(func, attr, None))
54 return to
55
56
57 def structured_lists(*fields):
58
59 def decorator(func):
60
61 def wrapper(self, *args, **kw):
62 for key, acc in [f.split('.') for f in fields]:
63 if key in kw:
64 newkey = key + '.' + acc + (acc and '.' or '')
65 for i in range(len(kw[key])):
66 kw[newkey + str(i + 1)] = kw[key][i]
67 kw.pop(key)
68 return func(self, *args, **kw)
69 wrapper.__doc__ = "{0}\nLists: {1}".format(func.__doc__,
70 ', '.join(fields))
71 return add_attrs_from(func, to=wrapper)
72 return decorator
73
74
75 def http_body(field):
76
77 def decorator(func):
78
79 def wrapper(*args, **kw):
80 if filter(lambda x: not x in kw, (field, 'content_type')):
81 message = "{0} requires {1} and content_type arguments for " \
82 "building HTTP body".format(func.action, field)
83 raise KeyError(message)
84 kw['body'] = kw.pop(field)
85 kw['headers'] = {
86 'Content-Type': kw.pop('content_type'),
87 'Content-MD5': content_md5(kw['body']),
88 }
89 return func(*args, **kw)
90 wrapper.__doc__ = "{0}\nRequired HTTP Body: " \
91 "{1}".format(func.__doc__, field)
92 return add_attrs_from(func, to=wrapper)
93 return decorator
94
95
96 def destructure_object(value, into={}, prefix=''):
97 if isinstance(value, ResponseElement):
98 for name, attr in value.__dict__.items():
99 if name.startswith('_'):
100 continue
101 destructure_object(attr, into=into, prefix=prefix + '.' + name)
102 elif filter(lambda x: isinstance(value, x), (list, set, tuple)):
103 for index, element in [(prefix + '.' + str(i + 1), value[i])
104 for i in range(len(value))]:
105 destructure_object(element, into=into, prefix=index)
106 elif isinstance(value, bool):
107 into[prefix] = str(value).lower()
108 else:
109 into[prefix] = value
110
111
112 def structured_objects(*fields):
113
114 def decorator(func):
115
116 def wrapper(*args, **kw):
117 for field in filter(kw.has_key, fields):
118 destructure_object(kw.pop(field), into=kw, prefix=field)
119 return func(*args, **kw)
120 wrapper.__doc__ = "{0}\nObjects: {1}".format(func.__doc__,
121 ', '.join(fields))
122 return add_attrs_from(func, to=wrapper)
123 return decorator
124
125
126 def requires(*groups):
127
128 def decorator(func):
129
130 def wrapper(*args, **kw):
131 hasgroup = lambda x: len(x) == len(filter(kw.has_key, x))
132 if 1 != len(filter(hasgroup, groups)):
133 message = ' OR '.join(['+'.join(g) for g in groups])
134 message = "{0} requires {1} argument(s)" \
135 "".format(func.action, message)
136 raise KeyError(message)
137 return func(*args, **kw)
138 message = ' OR '.join(['+'.join(g) for g in groups])
139 wrapper.__doc__ = "{0}\nRequired: {1}".format(func.__doc__,
140 message)
141 return add_attrs_from(func, to=wrapper)
142 return decorator
143
144
145 def exclusive(*groups):
146
147 def decorator(func):
148
149 def wrapper(*args, **kw):
150 hasgroup = lambda x: len(x) == len(filter(kw.has_key, x))
151 if len(filter(hasgroup, groups)) not in (0, 1):
152 message = ' OR '.join(['+'.join(g) for g in groups])
153 message = "{0} requires either {1}" \
154 "".format(func.action, message)
155 raise KeyError(message)
156 return func(*args, **kw)
157 message = ' OR '.join(['+'.join(g) for g in groups])
158 wrapper.__doc__ = "{0}\nEither: {1}".format(func.__doc__,
159 message)
160 return add_attrs_from(func, to=wrapper)
161 return decorator
162
163
164 def dependent(field, *groups):
165
166 def decorator(func):
167
168 def wrapper(*args, **kw):
169 hasgroup = lambda x: len(x) == len(filter(kw.has_key, x))
170 if field in kw and 1 > len(filter(hasgroup, groups)):
171 message = ' OR '.join(['+'.join(g) for g in groups])
172 message = "{0} argument {1} requires {2}" \
173 "".format(func.action, field, message)
174 raise KeyError(message)
175 return func(*args, **kw)
176 message = ' OR '.join(['+'.join(g) for g in groups])
177 wrapper.__doc__ = "{0}\n{1} requires: {2}".format(func.__doc__,
178 field,
179 message)
180 return add_attrs_from(func, to=wrapper)
181 return decorator
182
183
184 def requires_some_of(*fields):
185
186 def decorator(func):
187
188 def wrapper(*args, **kw):
189 if not filter(kw.has_key, fields):
190 message = "{0} requires at least one of {1} argument(s)" \
191 "".format(func.action, ', '.join(fields))
192 raise KeyError(message)
193 return func(*args, **kw)
194 wrapper.__doc__ = "{0}\nSome Required: {1}".format(func.__doc__,
195 ', '.join(fields))
196 return add_attrs_from(func, to=wrapper)
197 return decorator
198
199
200 def boolean_arguments(*fields):
201
202 def decorator(func):
203
204 def wrapper(*args, **kw):
205 for field in filter(lambda x: isinstance(kw.get(x), bool), fields):
206 kw[field] = str(kw[field]).lower()
207 return func(*args, **kw)
208 wrapper.__doc__ = "{0}\nBooleans: {1}".format(func.__doc__,
209 ', '.join(fields))
210 return add_attrs_from(func, to=wrapper)
211 return decorator
212
213
214 def api_action(section, quota, restore, *api):
215
216 def decorator(func, quota=int(quota), restore=float(restore)):
217 version, accesskey, path = api_version_path[section]
218 action = ''.join(api or map(str.capitalize, func.func_name.split('_')))
219 if hasattr(boto.mws.response, action + 'Response'):
220 response = getattr(boto.mws.response, action + 'Response')
221 else:
222 response = ResponseFactory(action)
223 response._action = action
224
225 def wrapper(self, *args, **kw):
226 kw.setdefault(accesskey, getattr(self, accesskey, None))
227 if kw[accesskey] is None:
228 message = "{0} requires {1} argument. Set the " \
229 "MWSConnection.{2} attribute?" \
230 "".format(action, accesskey, accesskey)
231 raise KeyError(message)
232 kw['Action'] = action
233 kw['Version'] = version
234 return func(self, path, response, *args, **kw)
235 for attr in decorated_attrs:
236 setattr(wrapper, attr, locals().get(attr))
237 wrapper.__doc__ = "MWS {0}/{1} API call; quota={2} restore={3:.2f}\n" \
238 "{4}".format(action, version, quota, restore,
239 func.__doc__)
240 return wrapper
241 return decorator
242
243
244 class MWSConnection(AWSQueryConnection):
245
246 ResponseError = ResponseErrorFactory
247
248 def __init__(self, *args, **kw):
249 kw.setdefault('host', 'mws.amazonservices.com')
250 self.Merchant = kw.pop('Merchant', None) or kw.get('SellerId')
251 self.SellerId = kw.pop('SellerId', None) or self.Merchant
252 AWSQueryConnection.__init__(self, *args, **kw)
253
254 def _required_auth_capability(self):
255 return ['mws']
256
257 def post_request(self, path, params, cls, body='', headers={}, isXML=True):
258 """Make a POST request, optionally with a content body,
259 and return the response, optionally as raw text.
260 Modelled off of the inherited get_object/make_request flow.
261 """
262 request = self.build_base_http_request('POST', path, None, data=body,
263 params=params, headers=headers, host=self.server_name())
264 response = self._mexe(request, override_num_retries=None)
265 body = response.read()
266 boto.log.debug(body)
267 if not body:
268 boto.log.error('Null body %s' % body)
269 raise self.ResponseError(response.status, response.reason, body)
270 if response.status != 200:
271 boto.log.error('%s %s' % (response.status, response.reason))
272 boto.log.error('%s' % body)
273 raise self.ResponseError(response.status, response.reason, body)
274 if not isXML:
275 digest = response.getheader('Content-MD5')
276 assert content_md5(body) == digest
277 return body
278 obj = cls(self)
279 h = XmlHandler(obj, self)
280 xml.sax.parseString(body, h)
281 return obj
282
283 def method_for(self, name):
284 """Return the MWS API method referred to in the argument.
285 The named method can be in CamelCase or underlined_lower_case.
286 This is the complement to MWSConnection.any_call.action
287 """
288 # this looks ridiculous but it should be better than regex
289 action = '_' in name and string.capwords(name, '_') or name
290 attribs = [getattr(self, m) for m in dir(self)]
291 ismethod = lambda m: type(m) is type(self.method_for)
292 ismatch = lambda m: getattr(m, 'action', None) == action
293 method = filter(ismatch, filter(ismethod, attribs))
294 return method and method[0] or None
295
296 def iter_call(self, call, *args, **kw):
297 """Pass a call name as the first argument and a generator
298 is returned for the initial response and any continuation
299 call responses made using the NextToken.
300 """
301 method = self.method_for(call)
302 assert method, 'No call named "{0}"'.format(call)
303 return self.iter_response(method(*args, **kw))
304
305 def iter_response(self, response):
306 """Pass a call's response as the initial argument and a
307 generator is returned for the initial response and any
308 continuation call responses made using the NextToken.
309 """
310 yield response
311 more = self.method_for(response._action + 'ByNextToken')
312 while more and response._result.HasNext == 'true':
313 response = more(NextToken=response._result.NextToken)
314 yield response
315
316 @boolean_arguments('PurgeAndReplace')
317 @http_body('FeedContent')
318 @structured_lists('MarketplaceIdList.Id')
319 @requires(['FeedType'])
320 @api_action('Feeds', 15, 120)
321 def submit_feed(self, path, response, headers={}, body='', **kw):
322 """Uploads a feed for processing by Amazon MWS.
323 """
324 return self.post_request(path, kw, response, body=body,
325 headers=headers)
326
327 @structured_lists('FeedSubmissionIdList.Id', 'FeedTypeList.Type',
328 'FeedProcessingStatusList.Status')
329 @api_action('Feeds', 10, 45)
330 def get_feed_submission_list(self, path, response, **kw):
331 """Returns a list of all feed submissions submitted in the
332 previous 90 days.
333 """
334 return self.post_request(path, kw, response)
335
336 @requires(['NextToken'])
337 @api_action('Feeds', 0, 0)
338 def get_feed_submission_list_by_next_token(self, path, response, **kw):
339 """Returns a list of feed submissions using the NextToken parameter.
340 """
341 return self.post_request(path, kw, response)
342
343 @structured_lists('FeedTypeList.Type', 'FeedProcessingStatusList.Status')
344 @api_action('Feeds', 10, 45)
345 def get_feed_submission_count(self, path, response, **kw):
346 """Returns a count of the feeds submitted in the previous 90 days.
347 """
348 return self.post_request(path, kw, response)
349
350 @structured_lists('FeedSubmissionIdList.Id', 'FeedTypeList.Type')
351 @api_action('Feeds', 10, 45)
352 def cancel_feed_submissions(self, path, response, **kw):
353 """Cancels one or more feed submissions and returns a
354 count of the feed submissions that were canceled.
355 """
356 return self.post_request(path, kw, response)
357
358 @requires(['FeedSubmissionId'])
359 @api_action('Feeds', 15, 60)
360 def get_feed_submission_result(self, path, response, **kw):
361 """Returns the feed processing report.
362 """
363 return self.post_request(path, kw, response, isXML=False)
364
365 def get_service_status(self, **kw):
366 """Instruct the user on how to get service status.
367 """
368 message = "Use {0}.get_(section)_service_status(), " \
369 "where (section) is one of the following: " \
370 "{1}".format(self.__class__.__name__,
371 ', '.join(map(str.lower, api_version_path.keys())))
372 raise AttributeError(message)
373
374 @structured_lists('MarketplaceIdList.Id')
375 @boolean_arguments('ReportOptions=ShowSalesChannel')
376 @requires(['ReportType'])
377 @api_action('Reports', 15, 60)
378 def request_report(self, path, response, **kw):
379 """Creates a report request and submits the request to Amazon MWS.
380 """
381 return self.post_request(path, kw, response)
382
383 @structured_lists('ReportRequestIdList.Id', 'ReportTypeList.Type',
384 'ReportProcessingStatusList.Status')
385 @api_action('Reports', 10, 45)
386 def get_report_request_list(self, path, response, **kw):
387 """Returns a list of report requests that you can use to get the
388 ReportRequestId for a report.
389 """
390 return self.post_request(path, kw, response)
391
392 @requires(['NextToken'])
393 @api_action('Reports', 0, 0)
394 def get_report_request_list_by_next_token(self, path, response, **kw):
395 """Returns a list of report requests using the NextToken,
396 which was supplied by a previous request to either
397 GetReportRequestListByNextToken or GetReportRequestList, where
398 the value of HasNext was true in that previous request.
399 """
400 return self.post_request(path, kw, response)
401
402 @structured_lists('ReportTypeList.Type',
403 'ReportProcessingStatusList.Status')
404 @api_action('Reports', 10, 45)
405 def get_report_request_count(self, path, response, **kw):
406 """Returns a count of report requests that have been submitted
407 to Amazon MWS for processing.
408 """
409 return self.post_request(path, kw, response)
410
411 @api_action('Reports', 10, 45)
412 def cancel_report_requests(self, path, response, **kw):
413 """Cancel one or more report requests, returning the count of the
414 canceled report requests and the report request information.
415 """
416 return self.post_request(path, kw, response)
417
418 @boolean_arguments('Acknowledged')
419 @structured_lists('ReportRequestIdList.Id', 'ReportTypeList.Type')
420 @api_action('Reports', 10, 60)
421 def get_report_list(self, path, response, **kw):
422 """Returns a list of reports that were created in the previous
423 90 days that match the query parameters.
424 """
425 return self.post_request(path, kw, response)
426
427 @requires(['NextToken'])
428 @api_action('Reports', 0, 0)
429 def get_report_list_by_next_token(self, path, response, **kw):
430 """Returns a list of reports using the NextToken, which
431 was supplied by a previous request to either
432 GetReportListByNextToken or GetReportList, where the
433 value of HasNext was true in the previous call.
434 """
435 return self.post_request(path, kw, response)
436
437 @boolean_arguments('Acknowledged')
438 @structured_lists('ReportTypeList.Type')
439 @api_action('Reports', 10, 45)
440 def get_report_count(self, path, response, **kw):
441 """Returns a count of the reports, created in the previous 90 days,
442 with a status of _DONE_ and that are available for download.
443 """
444 return self.post_request(path, kw, response)
445
446 @requires(['ReportId'])
447 @api_action('Reports', 15, 60)
448 def get_report(self, path, response, **kw):
449 """Returns the contents of a report.
450 """
451 return self.post_request(path, kw, response, isXML=False)
452
453 @requires(['ReportType', 'Schedule'])
454 @api_action('Reports', 10, 45)
455 def manage_report_schedule(self, path, response, **kw):
456 """Creates, updates, or deletes a report request schedule for
457 a specified report type.
458 """
459 return self.post_request(path, kw, response)
460
461 @structured_lists('ReportTypeList.Type')
462 @api_action('Reports', 10, 45)
463 def get_report_schedule_list(self, path, response, **kw):
464 """Returns a list of order report requests that are scheduled
465 to be submitted to Amazon MWS for processing.
466 """
467 return self.post_request(path, kw, response)
468
469 @requires(['NextToken'])
470 @api_action('Reports', 0, 0)
471 def get_report_schedule_list_by_next_token(self, path, response, **kw):
472 """Returns a list of report requests using the NextToken,
473 which was supplied by a previous request to either
474 GetReportScheduleListByNextToken or GetReportScheduleList,
475 where the value of HasNext was true in that previous request.
476 """
477 return self.post_request(path, kw, response)
478
479 @structured_lists('ReportTypeList.Type')
480 @api_action('Reports', 10, 45)
481 def get_report_schedule_count(self, path, response, **kw):
482 """Returns a count of order report requests that are scheduled
483 to be submitted to Amazon MWS.
484 """
485 return self.post_request(path, kw, response)
486
487 @boolean_arguments('Acknowledged')
488 @requires(['ReportIdList'])
489 @structured_lists('ReportIdList.Id')
490 @api_action('Reports', 10, 45)
491 def update_report_acknowledgements(self, path, response, **kw):
492 """Updates the acknowledged status of one or more reports.
493 """
494 return self.post_request(path, kw, response)
495
496 @requires(['ShipFromAddress', 'InboundShipmentPlanRequestItems'])
497 @structured_objects('ShipFromAddress', 'InboundShipmentPlanRequestItems')
498 @api_action('Inbound', 30, 0.5)
499 def create_inbound_shipment_plan(self, path, response, **kw):
500 """Returns the information required to create an inbound shipment.
501 """
502 return self.post_request(path, kw, response)
503
504 @requires(['ShipmentId', 'InboundShipmentHeader', 'InboundShipmentItems'])
505 @structured_objects('InboundShipmentHeader', 'InboundShipmentItems')
506 @api_action('Inbound', 30, 0.5)
507 def create_inbound_shipment(self, path, response, **kw):
508 """Creates an inbound shipment.
509 """
510 return self.post_request(path, kw, response)
511
512 @requires(['ShipmentId'])
513 @structured_objects('InboundShipmentHeader', 'InboundShipmentItems')
514 @api_action('Inbound', 30, 0.5)
515 def update_inbound_shipment(self, path, response, **kw):
516 """Updates an existing inbound shipment. Amazon documentation
517 is ambiguous as to whether the InboundShipmentHeader and
518 InboundShipmentItems arguments are required.
519 """
520 return self.post_request(path, kw, response)
521
522 @requires_some_of('ShipmentIdList', 'ShipmentStatusList')
523 @structured_lists('ShipmentIdList.Id', 'ShipmentStatusList.Status')
524 @api_action('Inbound', 30, 0.5)
525 def list_inbound_shipments(self, path, response, **kw):
526 """Returns a list of inbound shipments based on criteria that
527 you specify.
528 """
529 return self.post_request(path, kw, response)
530
531 @requires(['NextToken'])
532 @api_action('Inbound', 30, 0.5)
533 def list_inbound_shipments_by_next_token(self, path, response, **kw):
534 """Returns the next page of inbound shipments using the NextToken
535 parameter.
536 """
537 return self.post_request(path, kw, response)
538
539 @requires(['ShipmentId'], ['LastUpdatedAfter', 'LastUpdatedBefore'])
540 @api_action('Inbound', 30, 0.5)
541 def list_inbound_shipment_items(self, path, response, **kw):
542 """Returns a list of items in a specified inbound shipment, or a
543 list of items that were updated within a specified time frame.
544 """
545 return self.post_request(path, kw, response)
546
547 @requires(['NextToken'])
548 @api_action('Inbound', 30, 0.5)
549 def list_inbound_shipment_items_by_next_token(self, path, response, **kw):
550 """Returns the next page of inbound shipment items using the
551 NextToken parameter.
552 """
553 return self.post_request(path, kw, response)
554
555 @api_action('Inbound', 2, 300, 'GetServiceStatus')
556 def get_inbound_service_status(self, path, response, **kw):
557 """Returns the operational status of the Fulfillment Inbound
558 Shipment API section.
559 """
560 return self.post_request(path, kw, response)
561
562 @requires(['SellerSkus'], ['QueryStartDateTime'])
563 @structured_lists('SellerSkus.member')
564 @api_action('Inventory', 30, 0.5)
565 def list_inventory_supply(self, path, response, **kw):
566 """Returns information about the availability of a seller's
567 inventory.
568 """
569 return self.post_request(path, kw, response)
570
571 @requires(['NextToken'])
572 @api_action('Inventory', 30, 0.5)
573 def list_inventory_supply_by_next_token(self, path, response, **kw):
574 """Returns the next page of information about the availability
575 of a seller's inventory using the NextToken parameter.
576 """
577 return self.post_request(path, kw, response)
578
579 @api_action('Inventory', 2, 300, 'GetServiceStatus')
580 def get_inventory_service_status(self, path, response, **kw):
581 """Returns the operational status of the Fulfillment Inventory
582 API section.
583 """
584 return self.post_request(path, kw, response)
585
586 @structured_objects('Address', 'Items')
587 @requires(['Address', 'Items'])
588 @api_action('Outbound', 30, 0.5)
589 def get_fulfillment_preview(self, path, response, **kw):
590 """Returns a list of fulfillment order previews based on items
591 and shipping speed categories that you specify.
592 """
593 return self.post_request(path, kw, response)
594
595 @structured_objects('DestinationAddress', 'Items')
596 @requires(['SellerFulfillmentOrderId', 'DisplayableOrderId',
597 'ShippingSpeedCategory', 'DisplayableOrderDateTime',
598 'DestinationAddress', 'DisplayableOrderComment',
599 'Items'])
600 @api_action('Outbound', 30, 0.5)
601 def create_fulfillment_order(self, path, response, **kw):
602 """Requests that Amazon ship items from the seller's inventory
603 to a destination address.
604 """
605 return self.post_request(path, kw, response)
606
607 @requires(['SellerFulfillmentOrderId'])
608 @api_action('Outbound', 30, 0.5)
609 def get_fulfillment_order(self, path, response, **kw):
610 """Returns a fulfillment order based on a specified
611 SellerFulfillmentOrderId.
612 """
613 return self.post_request(path, kw, response)
614
615 @api_action('Outbound', 30, 0.5)
616 def list_all_fulfillment_orders(self, path, response, **kw):
617 """Returns a list of fulfillment orders fulfilled after (or
618 at) a specified date or by fulfillment method.
619 """
620 return self.post_request(path, kw, response)
621
622 @requires(['NextToken'])
623 @api_action('Outbound', 30, 0.5)
624 def list_all_fulfillment_orders_by_next_token(self, path, response, **kw):
625 """Returns the next page of inbound shipment items using the
626 NextToken parameter.
627 """
628 return self.post_request(path, kw, response)
629
630 @requires(['SellerFulfillmentOrderId'])
631 @api_action('Outbound', 30, 0.5)
632 def cancel_fulfillment_order(self, path, response, **kw):
633 """Requests that Amazon stop attempting to fulfill an existing
634 fulfillment order.
635 """
636 return self.post_request(path, kw, response)
637
638 @api_action('Outbound', 2, 300, 'GetServiceStatus')
639 def get_outbound_service_status(self, path, response, **kw):
640 """Returns the operational status of the Fulfillment Outbound
641 API section.
642 """
643 return self.post_request(path, kw, response)
644
645 @requires(['CreatedAfter'], ['LastUpdatedAfter'])
646 @exclusive(['CreatedAfter'], ['LastUpdatedAfter'])
647 @dependent('CreatedBefore', ['CreatedAfter'])
648 @exclusive(['LastUpdatedAfter'], ['BuyerEmail'], ['SellerOrderId'])
649 @dependent('LastUpdatedBefore', ['LastUpdatedAfter'])
650 @exclusive(['CreatedAfter'], ['LastUpdatedBefore'])
651 @requires(['MarketplaceId'])
652 @structured_objects('OrderTotal', 'ShippingAddress',
653 'PaymentExecutionDetail')
654 @structured_lists('MarketplaceId.Id', 'OrderStatus.Status',
655 'FulfillmentChannel.Channel', 'PaymentMethod.')
656 @api_action('Orders', 6, 60)
657 def list_orders(self, path, response, **kw):
658 """Returns a list of orders created or updated during a time
659 frame that you specify.
660 """
661 toggle = set(('FulfillmentChannel.Channel.1',
662 'OrderStatus.Status.1', 'PaymentMethod.1',
663 'LastUpdatedAfter', 'LastUpdatedBefore'))
664 for do, dont in {
665 'BuyerEmail': toggle.union(['SellerOrderId']),
666 'SellerOrderId': toggle.union(['BuyerEmail']),
667 }.items():
668 if do in kw and filter(kw.has_key, dont):
669 message = "Don't include {0} when specifying " \
670 "{1}".format(' or '.join(dont), do)
671 raise AssertionError(message)
672 return self.post_request(path, kw, response)
673
674 @requires(['NextToken'])
675 @api_action('Orders', 6, 60)
676 def list_orders_by_next_token(self, path, response, **kw):
677 """Returns the next page of orders using the NextToken value
678 that was returned by your previous request to either
679 ListOrders or ListOrdersByNextToken.
680 """
681 return self.post_request(path, kw, response)
682
683 @requires(['AmazonOrderId'])
684 @structured_lists('AmazonOrderId.Id')
685 @api_action('Orders', 6, 60)
686 def get_order(self, path, response, **kw):
687 """Returns an order for each AmazonOrderId that you specify.
688 """
689 return self.post_request(path, kw, response)
690
691 @requires(['AmazonOrderId'])
692 @api_action('Orders', 30, 2)
693 def list_order_items(self, path, response, **kw):
694 """Returns order item information for an AmazonOrderId that
695 you specify.
696 """
697 return self.post_request(path, kw, response)
698
699 @requires(['NextToken'])
700 @api_action('Orders', 30, 2)
701 def list_order_items_by_next_token(self, path, response, **kw):
702 """Returns the next page of order items using the NextToken
703 value that was returned by your previous request to either
704 ListOrderItems or ListOrderItemsByNextToken.
705 """
706 return self.post_request(path, kw, response)
707
708 @api_action('Orders', 2, 300, 'GetServiceStatus')
709 def get_orders_service_status(self, path, response, **kw):
710 """Returns the operational status of the Orders API section.
711 """
712 return self.post_request(path, kw, response)
713
714 @requires(['MarketplaceId', 'Query'])
715 @api_action('Products', 20, 20)
716 def list_matching_products(self, path, response, **kw):
717 """Returns a list of products and their attributes, ordered
718 by relevancy, based on a search query that you specify.
719 """
720 return self.post_request(path, kw, response)
721
722 @requires(['MarketplaceId', 'ASINList'])
723 @structured_lists('ASINList.ASIN')
724 @api_action('Products', 20, 20)
725 def get_matching_product(self, path, response, **kw):
726 """Returns a list of products and their attributes, based on
727 a list of ASIN values that you specify.
728 """
729 return self.post_request(path, kw, response)
730
731 @requires(['MarketplaceId', 'IdType', 'IdList'])
732 @structured_lists('IdList.Id')
733 @api_action('Products', 20, 20)
734 def get_matching_product_for_id(self, path, response, **kw):
735 """Returns a list of products and their attributes, based on
736 a list of Product IDs that you specify.
737 """
738 return self.post_request(path, kw, response)
739
740 @requires(['MarketplaceId', 'SellerSKUList'])
741 @structured_lists('SellerSKUList.SellerSKU')
742 @api_action('Products', 20, 10, 'GetCompetitivePricingForSKU')
743 def get_competitive_pricing_for_sku(self, path, response, **kw):
744 """Returns the current competitive pricing of a product,
745 based on the SellerSKUs and MarketplaceId that you specify.
746 """
747 return self.post_request(path, kw, response)
748
749 @requires(['MarketplaceId', 'ASINList'])
750 @structured_lists('ASINList.ASIN')
751 @api_action('Products', 20, 10, 'GetCompetitivePricingForASIN')
752 def get_competitive_pricing_for_asin(self, path, response, **kw):
753 """Returns the current competitive pricing of a product,
754 based on the ASINs and MarketplaceId that you specify.
755 """
756 return self.post_request(path, kw, response)
757
758 @requires(['MarketplaceId', 'SellerSKUList'])
759 @structured_lists('SellerSKUList.SellerSKU')
760 @api_action('Products', 20, 5, 'GetLowestOfferListingsForSKU')
761 def get_lowest_offer_listings_for_sku(self, path, response, **kw):
762 """Returns the lowest price offer listings for a specific
763 product by item condition and SellerSKUs.
764 """
765 return self.post_request(path, kw, response)
766
767 @requires(['MarketplaceId', 'ASINList'])
768 @structured_lists('ASINList.ASIN')
769 @api_action('Products', 20, 5, 'GetLowestOfferListingsForASIN')
770 def get_lowest_offer_listings_for_asin(self, path, response, **kw):
771 """Returns the lowest price offer listings for a specific
772 product by item condition and ASINs.
773 """
774 return self.post_request(path, kw, response)
775
776 @requires(['MarketplaceId', 'SellerSKU'])
777 @api_action('Products', 20, 20, 'GetProductCategoriesForSKU')
778 def get_product_categories_for_sku(self, path, response, **kw):
779 """Returns the product categories that a SellerSKU belongs to.
780 """
781 return self.post_request(path, kw, response)
782
783 @requires(['MarketplaceId', 'ASIN'])
784 @api_action('Products', 20, 20, 'GetProductCategoriesForASIN')
785 def get_product_categories_for_asin(self, path, response, **kw):
786 """Returns the product categories that an ASIN belongs to.
787 """
788 return self.post_request(path, kw, response)
789
790 @api_action('Products', 2, 300, 'GetServiceStatus')
791 def get_products_service_status(self, path, response, **kw):
792 """Returns the operational status of the Products API section.
793 """
794 return self.post_request(path, kw, response)
795
796 @api_action('Sellers', 15, 60)
797 def list_marketplace_participations(self, path, response, **kw):
798 """Returns a list of marketplaces that the seller submitting
799 the request can sell in, and a list of participations that
800 include seller-specific information in that marketplace.
801 """
802 return self.post_request(path, kw, response)
803
804 @requires(['NextToken'])
805 @api_action('Sellers', 15, 60)
806 def list_marketplace_participations_by_next_token(self, path, response,
807 **kw):
808 """Returns the next page of marketplaces and participations
809 using the NextToken value that was returned by your
810 previous request to either ListMarketplaceParticipations
811 or ListMarketplaceParticipationsByNextToken.
812 """
813 return self.post_request(path, kw, response)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698