Home | History | Annotate | Download | only in mws
      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 copy
      4 # of this software and associated documentation files (the "Software"), to
      5 # deal in the Software without restriction, including without limitation the
      6 # rights to use, copy, modify, merge, publish, dis- tribute, sublicense, and/or
      7 # sell copies of the Software, and to permit persons to whom the Software is
      8 # furnished to do so, subject to the fol- lowing conditions:
      9 #
     10 # The above copyright notice and this permission notice shall be included in
     11 # all copies or substantial portions of the Software.
     12 #
     13 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     14 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- ITY,
     15 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     16 # AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     17 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     18 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     19 from decimal import Decimal
     20 from boto.compat import filter, map
     21 
     22 
     23 class ComplexType(dict):
     24     _value = 'Value'
     25 
     26     def __repr__(self):
     27         return '{0}{1}'.format(getattr(self, self._value, None), self.copy())
     28 
     29     def __str__(self):
     30         return str(getattr(self, self._value, ''))
     31 
     32 
     33 class DeclarativeType(object):
     34     def __init__(self, _hint=None, **kw):
     35         self._value = None
     36         if _hint is not None:
     37             self._hint = _hint
     38             return
     39 
     40         class JITResponse(ResponseElement):
     41             pass
     42         self._hint = JITResponse
     43         self._hint.__name__ = 'JIT_{0}/{1}'.format(self.__class__.__name__,
     44                                                    hex(id(self._hint))[2:])
     45         for name, value in kw.items():
     46             setattr(self._hint, name, value)
     47 
     48     def __repr__(self):
     49         parent = getattr(self, '_parent', None)
     50         return '<{0}_{1}/{2}_{3}>'.format(self.__class__.__name__,
     51                                           parent and parent._name or '?',
     52                                           getattr(self, '_name', '?'),
     53                                           hex(id(self.__class__)))
     54 
     55     def setup(self, parent, name, *args, **kw):
     56         self._parent = parent
     57         self._name = name
     58         self._clone = self.__class__(_hint=self._hint)
     59         self._clone._parent = parent
     60         self._clone._name = name
     61         setattr(self._parent, self._name, self._clone)
     62 
     63     def start(self, *args, **kw):
     64         raise NotImplementedError
     65 
     66     def end(self, *args, **kw):
     67         raise NotImplementedError
     68 
     69     def teardown(self, *args, **kw):
     70         setattr(self._parent, self._name, self._value)
     71 
     72 
     73 class Element(DeclarativeType):
     74     def start(self, *args, **kw):
     75         self._value = self._hint(parent=self._parent, **kw)
     76         return self._value
     77 
     78     def end(self, *args, **kw):
     79         pass
     80 
     81 
     82 class SimpleList(DeclarativeType):
     83     def __init__(self, *args, **kw):
     84         super(SimpleList, self).__init__(*args, **kw)
     85         self._value = []
     86 
     87     def start(self, *args, **kw):
     88         return None
     89 
     90     def end(self, name, value, *args, **kw):
     91         self._value.append(value)
     92 
     93 
     94 class ElementList(SimpleList):
     95     def start(self, *args, **kw):
     96         value = self._hint(parent=self._parent, **kw)
     97         self._value.append(value)
     98         return value
     99 
    100     def end(self, *args, **kw):
    101         pass
    102 
    103 
    104 class MemberList(Element):
    105     def __init__(self, _member=None, _hint=None, *args, **kw):
    106         message = 'Invalid `member` specification in {0}'.format(self.__class__.__name__)
    107         assert 'member' not in kw, message
    108         if _member is None:
    109             if _hint is None:
    110                 super(MemberList, self).__init__(*args, member=ElementList(**kw))
    111             else:
    112                 super(MemberList, self).__init__(_hint=_hint)
    113         else:
    114             if _hint is None:
    115                 if issubclass(_member, DeclarativeType):
    116                     member = _member(**kw)
    117                 else:
    118                     member = ElementList(_member, **kw)
    119                 super(MemberList, self).__init__(*args, member=member)
    120             else:
    121                 message = 'Nonsensical {0} hint {1!r}'.format(self.__class__.__name__,
    122                                                               _hint)
    123                 raise AssertionError(message)
    124 
    125     def teardown(self, *args, **kw):
    126         if self._value is None:
    127             self._value = []
    128         else:
    129             if isinstance(self._value.member, DeclarativeType):
    130                 self._value.member = []
    131             self._value = self._value.member
    132         super(MemberList, self).teardown(*args, **kw)
    133 
    134 
    135 class ResponseFactory(object):
    136     def __init__(self, scopes=None):
    137         self.scopes = [] if scopes is None else scopes
    138 
    139     def element_factory(self, name, parent):
    140         class DynamicElement(parent):
    141             _name = name
    142         setattr(DynamicElement, '__name__', str(name))
    143         return DynamicElement
    144 
    145     def search_scopes(self, key):
    146         for scope in self.scopes:
    147             if hasattr(scope, key):
    148                 return getattr(scope, key)
    149             if hasattr(scope, '__getitem__'):
    150                 if key in scope:
    151                     return scope[key]
    152 
    153     def find_element(self, action, suffix, parent):
    154         element = self.search_scopes(action + suffix)
    155         if element is not None:
    156             return element
    157         if action.endswith('ByNextToken'):
    158             element = self.search_scopes(action[:-len('ByNextToken')] + suffix)
    159             if element is not None:
    160                 return self.element_factory(action + suffix, element)
    161         return self.element_factory(action + suffix, parent)
    162 
    163     def __call__(self, action, connection=None):
    164         response = self.find_element(action, 'Response', Response)
    165         if not hasattr(response, action + 'Result'):
    166             result = self.find_element(action, 'Result', ResponseElement)
    167             setattr(response, action + 'Result', Element(result))
    168         return response(connection=connection)
    169 
    170 
    171 def strip_namespace(func):
    172     def wrapper(self, name, *args, **kw):
    173         if self._namespace is not None:
    174             if name.startswith(self._namespace + ':'):
    175                 name = name[len(self._namespace + ':'):]
    176         return func(self, name, *args, **kw)
    177     return wrapper
    178 
    179 
    180 class ResponseElement(dict):
    181     _override = {}
    182     _name = None
    183     _namespace = None
    184 
    185     def __init__(self, connection=None, name=None, parent=None, attrs=None):
    186         if parent is not None and self._namespace is None:
    187             self._namespace = parent._namespace
    188         if connection is not None:
    189             self._connection = connection
    190         self._name = name or self._name or self.__class__.__name__
    191         self._declared('setup', attrs=attrs)
    192         dict.__init__(self, attrs and attrs.copy() or {})
    193 
    194     def _declared(self, op, **kw):
    195         def inherit(obj):
    196             result = {}
    197             for cls in getattr(obj, '__bases__', ()):
    198                 result.update(inherit(cls))
    199             result.update(obj.__dict__)
    200             return result
    201 
    202         scope = inherit(self.__class__)
    203         scope.update(self.__dict__)
    204         declared = lambda attr: isinstance(attr[1], DeclarativeType)
    205         for name, node in filter(declared, scope.items()):
    206             getattr(node, op)(self, name, parentname=self._name, **kw)
    207 
    208     @property
    209     def connection(self):
    210         return self._connection
    211 
    212     def __repr__(self):
    213         render = lambda pair: '{0!s}: {1!r}'.format(*pair)
    214         do_show = lambda pair: not pair[0].startswith('_')
    215         attrs = filter(do_show, self.__dict__.items())
    216         name = self.__class__.__name__
    217         if name.startswith('JIT_'):
    218             name = '^{0}^'.format(self._name or '')
    219         return '{0}{1!r}({2})'.format(
    220             name, self.copy(), ', '.join(map(render, attrs)))
    221 
    222     def _type_for(self, name, attrs):
    223         return self._override.get(name, globals().get(name, ResponseElement))
    224 
    225     @strip_namespace
    226     def startElement(self, name, attrs, connection):
    227         attribute = getattr(self, name, None)
    228         if isinstance(attribute, DeclarativeType):
    229             return attribute.start(name=name, attrs=attrs,
    230                                    connection=connection)
    231         elif attrs.getLength():
    232             setattr(self, name, ComplexType(attrs.copy()))
    233         else:
    234             return None
    235 
    236     @strip_namespace
    237     def endElement(self, name, value, connection):
    238         attribute = getattr(self, name, None)
    239         if name == self._name:
    240             self._declared('teardown')
    241         elif isinstance(attribute, DeclarativeType):
    242             attribute.end(name=name, value=value, connection=connection)
    243         elif isinstance(attribute, ComplexType):
    244             setattr(attribute, attribute._value, value)
    245         else:
    246             setattr(self, name, value)
    247 
    248 
    249 class Response(ResponseElement):
    250     ResponseMetadata = Element()
    251 
    252     @strip_namespace
    253     def startElement(self, name, attrs, connection):
    254         if name == self._name:
    255             self.update(attrs)
    256         else:
    257             return super(Response, self).startElement(name, attrs, connection)
    258 
    259     @property
    260     def _result(self):
    261         return getattr(self, self._action + 'Result', None)
    262 
    263     @property
    264     def _action(self):
    265         return (self._name or self.__class__.__name__)[:-len('Response')]
    266 
    267 
    268 class ResponseResultList(Response):
    269     _ResultClass = ResponseElement
    270 
    271     def __init__(self, *args, **kw):
    272         setattr(self, self._action + 'Result', ElementList(self._ResultClass))
    273         super(ResponseResultList, self).__init__(*args, **kw)
    274 
    275 
    276 class FeedSubmissionInfo(ResponseElement):
    277     pass
    278 
    279 
    280 class SubmitFeedResult(ResponseElement):
    281     FeedSubmissionInfo = Element(FeedSubmissionInfo)
    282 
    283 
    284 class GetFeedSubmissionListResult(ResponseElement):
    285     FeedSubmissionInfo = ElementList(FeedSubmissionInfo)
    286 
    287 
    288 class GetFeedSubmissionCountResult(ResponseElement):
    289     pass
    290 
    291 
    292 class CancelFeedSubmissionsResult(GetFeedSubmissionListResult):
    293     pass
    294 
    295 
    296 class GetServiceStatusResult(ResponseElement):
    297     Messages = Element(Messages=ElementList())
    298 
    299 
    300 class ReportRequestInfo(ResponseElement):
    301     pass
    302 
    303 
    304 class RequestReportResult(ResponseElement):
    305     ReportRequestInfo = Element()
    306 
    307 
    308 class GetReportRequestListResult(RequestReportResult):
    309     ReportRequestInfo = ElementList()
    310 
    311 
    312 class CancelReportRequestsResult(RequestReportResult):
    313     pass
    314 
    315 
    316 class GetReportListResult(ResponseElement):
    317     ReportInfo = ElementList()
    318 
    319 
    320 class ManageReportScheduleResult(ResponseElement):
    321     ReportSchedule = Element()
    322 
    323 
    324 class GetReportScheduleListResult(ManageReportScheduleResult):
    325     pass
    326 
    327 
    328 class UpdateReportAcknowledgementsResult(GetReportListResult):
    329     pass
    330 
    331 
    332 class CreateInboundShipmentPlanResult(ResponseElement):
    333     InboundShipmentPlans = MemberList(ShipToAddress=Element(),
    334                                       Items=MemberList())
    335 
    336 
    337 class ListInboundShipmentsResult(ResponseElement):
    338     ShipmentData = MemberList(ShipFromAddress=Element())
    339 
    340 
    341 class ListInboundShipmentItemsResult(ResponseElement):
    342     ItemData = MemberList()
    343 
    344 
    345 class ListInventorySupplyResult(ResponseElement):
    346     InventorySupplyList = MemberList(
    347         EarliestAvailability=Element(),
    348         SupplyDetail=MemberList(
    349             EarliestAvailableToPick=Element(),
    350             LatestAvailableToPick=Element(),
    351         )
    352     )
    353 
    354 
    355 class ComplexAmount(ResponseElement):
    356     _amount = 'Value'
    357 
    358     def __repr__(self):
    359         return '{0} {1}'.format(self.CurrencyCode, getattr(self, self._amount))
    360 
    361     def __float__(self):
    362         return float(getattr(self, self._amount))
    363 
    364     def __str__(self):
    365         return str(getattr(self, self._amount))
    366 
    367     @strip_namespace
    368     def startElement(self, name, attrs, connection):
    369         if name not in ('CurrencyCode', self._amount):
    370             message = 'Unrecognized tag {0} in ComplexAmount'.format(name)
    371             raise AssertionError(message)
    372         return super(ComplexAmount, self).startElement(name, attrs, connection)
    373 
    374     @strip_namespace
    375     def endElement(self, name, value, connection):
    376         if name == self._amount:
    377             value = Decimal(value)
    378         super(ComplexAmount, self).endElement(name, value, connection)
    379 
    380 
    381 class ComplexMoney(ComplexAmount):
    382     _amount = 'Amount'
    383 
    384 
    385 class ComplexWeight(ResponseElement):
    386     def __repr__(self):
    387         return '{0} {1}'.format(self.Value, self.Unit)
    388 
    389     def __float__(self):
    390         return float(self.Value)
    391 
    392     def __str__(self):
    393         return str(self.Value)
    394 
    395     @strip_namespace
    396     def startElement(self, name, attrs, connection):
    397         if name not in ('Unit', 'Value'):
    398             message = 'Unrecognized tag {0} in ComplexWeight'.format(name)
    399             raise AssertionError(message)
    400         return super(ComplexWeight, self).startElement(name, attrs, connection)
    401 
    402     @strip_namespace
    403     def endElement(self, name, value, connection):
    404         if name == 'Value':
    405             value = Decimal(value)
    406         super(ComplexWeight, self).endElement(name, value, connection)
    407 
    408 
    409 class Dimension(ComplexType):
    410     _value = 'Value'
    411 
    412 
    413 class ComplexDimensions(ResponseElement):
    414     _dimensions = ('Height', 'Length', 'Width', 'Weight')
    415 
    416     def __repr__(self):
    417         values = [getattr(self, key, None) for key in self._dimensions]
    418         values = filter(None, values)
    419         return 'x'.join(map('{0.Value:0.2f}{0[Units]}'.format, values))
    420 
    421     @strip_namespace
    422     def startElement(self, name, attrs, connection):
    423         if name not in self._dimensions:
    424             message = 'Unrecognized tag {0} in ComplexDimensions'.format(name)
    425             raise AssertionError(message)
    426         setattr(self, name, Dimension(attrs.copy()))
    427 
    428     @strip_namespace
    429     def endElement(self, name, value, connection):
    430         if name in self._dimensions:
    431             value = Decimal(value or '0')
    432         ResponseElement.endElement(self, name, value, connection)
    433 
    434 
    435 class FulfillmentPreviewItem(ResponseElement):
    436     EstimatedShippingWeight = Element(ComplexWeight)
    437 
    438 
    439 class FulfillmentPreview(ResponseElement):
    440     EstimatedShippingWeight = Element(ComplexWeight)
    441     EstimatedFees = MemberList(Amount=Element(ComplexAmount))
    442     UnfulfillablePreviewItems = MemberList(FulfillmentPreviewItem)
    443     FulfillmentPreviewShipments = MemberList(
    444         FulfillmentPreviewItems=MemberList(FulfillmentPreviewItem),
    445     )
    446 
    447 
    448 class GetFulfillmentPreviewResult(ResponseElement):
    449     FulfillmentPreviews = MemberList(FulfillmentPreview)
    450 
    451 
    452 class FulfillmentOrder(ResponseElement):
    453     DestinationAddress = Element()
    454     NotificationEmailList = MemberList(SimpleList)
    455 
    456 
    457 class GetFulfillmentOrderResult(ResponseElement):
    458     FulfillmentOrder = Element(FulfillmentOrder)
    459     FulfillmentShipment = MemberList(
    460         FulfillmentShipmentItem=MemberList(),
    461         FulfillmentShipmentPackage=MemberList(),
    462     )
    463     FulfillmentOrderItem = MemberList()
    464 
    465 
    466 class ListAllFulfillmentOrdersResult(ResponseElement):
    467     FulfillmentOrders = MemberList(FulfillmentOrder)
    468 
    469 
    470 class GetPackageTrackingDetailsResult(ResponseElement):
    471     ShipToAddress = Element()
    472     TrackingEvents = MemberList(EventAddress=Element())
    473 
    474 
    475 class Image(ResponseElement):
    476     pass
    477 
    478 
    479 class AttributeSet(ResponseElement):
    480     ItemDimensions = Element(ComplexDimensions)
    481     ListPrice = Element(ComplexMoney)
    482     PackageDimensions = Element(ComplexDimensions)
    483     SmallImage = Element(Image)
    484 
    485 
    486 class ItemAttributes(AttributeSet):
    487     Languages = Element(Language=ElementList())
    488 
    489     def __init__(self, *args, **kw):
    490         names = ('Actor', 'Artist', 'Author', 'Creator', 'Director',
    491                  'Feature', 'Format', 'GemType', 'MaterialType',
    492                  'MediaType', 'OperatingSystem', 'Platform')
    493         for name in names:
    494             setattr(self, name, SimpleList())
    495         super(ItemAttributes, self).__init__(*args, **kw)
    496 
    497 
    498 class VariationRelationship(ResponseElement):
    499     Identifiers = Element(MarketplaceASIN=Element(),
    500                           SKUIdentifier=Element())
    501     GemType = SimpleList()
    502     MaterialType = SimpleList()
    503     OperatingSystem = SimpleList()
    504 
    505 
    506 class Price(ResponseElement):
    507     LandedPrice = Element(ComplexMoney)
    508     ListingPrice = Element(ComplexMoney)
    509     Shipping = Element(ComplexMoney)
    510 
    511 
    512 class CompetitivePrice(ResponseElement):
    513     Price = Element(Price)
    514 
    515 
    516 class CompetitivePriceList(ResponseElement):
    517     CompetitivePrice = ElementList(CompetitivePrice)
    518 
    519 
    520 class CompetitivePricing(ResponseElement):
    521     CompetitivePrices = Element(CompetitivePriceList)
    522     NumberOfOfferListings = SimpleList()
    523     TradeInValue = Element(ComplexMoney)
    524 
    525 
    526 class SalesRank(ResponseElement):
    527     pass
    528 
    529 
    530 class LowestOfferListing(ResponseElement):
    531     Qualifiers = Element(ShippingTime=Element())
    532     Price = Element(Price)
    533 
    534 
    535 class Offer(ResponseElement):
    536     BuyingPrice = Element(Price)
    537     RegularPrice = Element(ComplexMoney)
    538 
    539 
    540 class Product(ResponseElement):
    541     _namespace = 'ns2'
    542     Identifiers = Element(MarketplaceASIN=Element(),
    543                           SKUIdentifier=Element())
    544     AttributeSets = Element(
    545         ItemAttributes=ElementList(ItemAttributes),
    546     )
    547     Relationships = Element(
    548         VariationParent=ElementList(VariationRelationship),
    549     )
    550     CompetitivePricing = ElementList(CompetitivePricing)
    551     SalesRankings = Element(
    552         SalesRank=ElementList(SalesRank),
    553     )
    554     LowestOfferListings = Element(
    555         LowestOfferListing=ElementList(LowestOfferListing),
    556     )
    557     Offers = Element(
    558         Offer=ElementList(Offer),
    559     )
    560 
    561 
    562 class ListMatchingProductsResult(ResponseElement):
    563     Products = Element(Product=ElementList(Product))
    564 
    565 
    566 class ProductsBulkOperationResult(ResponseElement):
    567     Product = Element(Product)
    568     Error = Element()
    569 
    570 
    571 class ProductsBulkOperationResponse(ResponseResultList):
    572     _ResultClass = ProductsBulkOperationResult
    573 
    574 
    575 class GetMatchingProductResponse(ProductsBulkOperationResponse):
    576     pass
    577 
    578 
    579 class GetMatchingProductForIdResult(ListMatchingProductsResult):
    580     pass
    581 
    582 
    583 class GetMatchingProductForIdResponse(ResponseResultList):
    584     _ResultClass = GetMatchingProductForIdResult
    585 
    586 
    587 class GetCompetitivePricingForSKUResponse(ProductsBulkOperationResponse):
    588     pass
    589 
    590 
    591 class GetCompetitivePricingForASINResponse(ProductsBulkOperationResponse):
    592     pass
    593 
    594 
    595 class GetLowestOfferListingsForSKUResponse(ProductsBulkOperationResponse):
    596     pass
    597 
    598 
    599 class GetLowestOfferListingsForASINResponse(ProductsBulkOperationResponse):
    600     pass
    601 
    602 
    603 class GetMyPriceForSKUResponse(ProductsBulkOperationResponse):
    604     pass
    605 
    606 
    607 class GetMyPriceForASINResponse(ProductsBulkOperationResponse):
    608     pass
    609 
    610 
    611 class ProductCategory(ResponseElement):
    612 
    613     def __init__(self, *args, **kw):
    614         setattr(self, 'Parent', Element(ProductCategory))
    615         super(ProductCategory, self).__init__(*args, **kw)
    616 
    617 
    618 class GetProductCategoriesResult(ResponseElement):
    619     Self = ElementList(ProductCategory)
    620 
    621 
    622 class GetProductCategoriesForSKUResult(GetProductCategoriesResult):
    623     pass
    624 
    625 
    626 class GetProductCategoriesForASINResult(GetProductCategoriesResult):
    627     pass
    628 
    629 
    630 class Order(ResponseElement):
    631     OrderTotal = Element(ComplexMoney)
    632     ShippingAddress = Element()
    633     PaymentExecutionDetail = Element(
    634         PaymentExecutionDetailItem=ElementList(
    635             PaymentExecutionDetailItem=Element(
    636                 Payment=Element(ComplexMoney)
    637             )
    638         )
    639     )
    640 
    641 
    642 class ListOrdersResult(ResponseElement):
    643     Orders = Element(Order=ElementList(Order))
    644 
    645 
    646 class GetOrderResult(ListOrdersResult):
    647     pass
    648 
    649 
    650 class OrderItem(ResponseElement):
    651     ItemPrice = Element(ComplexMoney)
    652     ShippingPrice = Element(ComplexMoney)
    653     GiftWrapPrice = Element(ComplexMoney)
    654     ItemTax = Element(ComplexMoney)
    655     ShippingTax = Element(ComplexMoney)
    656     GiftWrapTax = Element(ComplexMoney)
    657     ShippingDiscount = Element(ComplexMoney)
    658     PromotionDiscount = Element(ComplexMoney)
    659     PromotionIds = SimpleList()
    660     CODFee = Element(ComplexMoney)
    661     CODFeeDiscount = Element(ComplexMoney)
    662 
    663 
    664 class ListOrderItemsResult(ResponseElement):
    665     OrderItems = Element(OrderItem=ElementList(OrderItem))
    666 
    667 
    668 class ListMarketplaceParticipationsResult(ResponseElement):
    669     ListParticipations = Element(Participation=ElementList())
    670     ListMarketplaces = Element(Marketplace=ElementList())
    671 
    672 
    673 class ListRecommendationsResult(ResponseElement):
    674     ListingQualityRecommendations = MemberList(ItemIdentifier=Element())
    675 
    676 
    677 class Customer(ResponseElement):
    678     PrimaryContactInfo = Element()
    679     ShippingAddressList = Element(ShippingAddress=ElementList())
    680     AssociatedMarketplaces = Element(MarketplaceDomain=ElementList())
    681 
    682 
    683 class ListCustomersResult(ResponseElement):
    684     CustomerList = Element(Customer=ElementList(Customer))
    685 
    686 
    687 class GetCustomersForCustomerIdResult(ListCustomersResult):
    688     pass
    689 
    690 
    691 class CartItem(ResponseElement):
    692     CurrentPrice = Element(ComplexMoney)
    693     SalePrice = Element(ComplexMoney)
    694 
    695 
    696 class Cart(ResponseElement):
    697     ActiveCartItemList = Element(CartItem=ElementList(CartItem))
    698     SavedCartItemList = Element(CartItem=ElementList(CartItem))
    699 
    700 
    701 class ListCartsResult(ResponseElement):
    702     CartList = Element(Cart=ElementList(Cart))
    703 
    704 
    705 class GetCartsResult(ListCartsResult):
    706     pass
    707 
    708 
    709 class Destination(ResponseElement):
    710     AttributeList = MemberList()
    711 
    712 
    713 class ListRegisteredDestinationsResult(ResponseElement):
    714     DestinationList = MemberList(Destination)
    715 
    716 
    717 class Subscription(ResponseElement):
    718     Destination = Element(Destination)
    719 
    720 
    721 class GetSubscriptionResult(ResponseElement):
    722     Subscription = Element(Subscription)
    723 
    724 
    725 class ListSubscriptionsResult(ResponseElement):
    726     SubscriptionList = MemberList(Subscription)
    727 
    728 
    729 class OrderReferenceDetails(ResponseElement):
    730     Buyer = Element()
    731     OrderTotal = Element(ComplexMoney)
    732     Destination = Element(PhysicalDestination=Element())
    733     SellerOrderAttributes = Element()
    734     OrderReferenceStatus = Element()
    735     Constraints = ElementList()
    736 
    737 
    738 class SetOrderReferenceDetailsResult(ResponseElement):
    739     OrderReferenceDetails = Element(OrderReferenceDetails)
    740 
    741 
    742 class GetOrderReferenceDetailsResult(SetOrderReferenceDetailsResult):
    743     pass
    744 
    745 
    746 class AuthorizationDetails(ResponseElement):
    747     AuthorizationAmount = Element(ComplexMoney)
    748     CapturedAmount = Element(ComplexMoney)
    749     AuthorizationFee = Element(ComplexMoney)
    750     AuthorizationStatus = Element()
    751 
    752 
    753 class AuthorizeResult(ResponseElement):
    754     AuthorizationDetails = Element(AuthorizationDetails)
    755 
    756 
    757 class GetAuthorizationDetailsResult(AuthorizeResult):
    758     pass
    759 
    760 
    761 class CaptureDetails(ResponseElement):
    762     CaptureAmount = Element(ComplexMoney)
    763     RefundedAmount = Element(ComplexMoney)
    764     CaptureFee = Element(ComplexMoney)
    765     CaptureStatus = Element()
    766 
    767 
    768 class CaptureResult(ResponseElement):
    769     CaptureDetails = Element(CaptureDetails)
    770 
    771 
    772 class GetCaptureDetailsResult(CaptureResult):
    773     pass
    774 
    775 
    776 class RefundDetails(ResponseElement):
    777     RefundAmount = Element(ComplexMoney)
    778     FeeRefunded = Element(ComplexMoney)
    779     RefundStatus = Element()
    780 
    781 
    782 class RefundResult(ResponseElement):
    783     RefundDetails = Element(RefundDetails)
    784 
    785 
    786 class GetRefundDetails(RefundResult):
    787     pass
    788