From a8693ac1e0f2b415b51e1573af30b1577985dee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Thu, 3 May 2018 18:55:14 +0200 Subject: [PATCH 01/19] clean input parameter --- mws/apis/reports.py | 4 +- mws/mws.py | 40 +++++++++++++---- .../request_methods/test_outboundshipments.py | 1 + tests/request_methods/test_reports.py | 43 ++++++++++++------- 4 files changed, 61 insertions(+), 27 deletions(-) diff --git a/mws/apis/reports.py b/mws/apis/reports.py index dc5f4141..adfa5862 100644 --- a/mws/apis/reports.py +++ b/mws/apis/reports.py @@ -3,7 +3,7 @@ """ from __future__ import absolute_import -import mws +from ..mws import MWS from .. import utils from ..decorators import next_token_action @@ -11,7 +11,7 @@ # TODO Add Schedule enumerations as constants -class Reports(mws.MWS): +class Reports(MWS): """ Amazon MWS Reports API diff --git a/mws/mws.py b/mws/mws.py index a1e833f3..52a57c07 100644 --- a/mws/mws.py +++ b/mws/mws.py @@ -57,6 +57,15 @@ class MWSError(Exception): response = None +class InputError(Exception): + def __init__(self, key, value, dtype): + self.message = 'the parameter: {}, expected a value of type {}'\ + ', got: {} with type {}'.format(key, dtype, value, type(value)) + + def __str__(self): + return self.message + + def calc_request_description(params): """ Returns a flatted string with the request description, built from the params dict. @@ -76,18 +85,31 @@ def calc_request_description(params): """ description_items = [] for item in sorted(params.keys()): - encoded_val = quote(str(params[item]), safe='-_.~') + encoded_val = params[item] description_items.append('{}={}'.format(item, encoded_val)) return '&'.join(description_items) def remove_empty(dict_): - """ - Returns dict_ with all empty values removed. - """ return {k: v for k, v in dict_.items() if v} +def clean_extra_data(extra_data): + extra_data_enc = dict() + for key, value in extra_data.items(): + if isinstance(value, (datetime.datetime, datetime.date)): + value = str(value.isoformat()) + if isinstance(value, (bool, int)): + value = str(value) + try: + value.lower() + value + '' + except: + """final validation, value not like a string""" + raise InputError(key, value, str) + extra_data_enc[key] = quote(value, safe='-_.~') + return extra_data_enc + + def remove_namespace(xml): """ Strips the namespace from XML document contained in a string. @@ -121,6 +143,7 @@ class DictWrapper(object): # TODO create a base class for DictWrapper and DataWrapper with all the keys we expect in responses. # This will make it easier to use either class in place of each other. # Either this, or pile everything into DataWrapper and make it able to handle all cases. + def __init__(self, xml, rootkey=None): self.original = xml self.response = None @@ -142,6 +165,7 @@ class DataWrapper(object): """ Text wrapper in charge of validating the hash sent by Amazon. """ + def __init__(self, data, header): self.original = data self.response = None @@ -250,10 +274,7 @@ def make_request(self, extra_data, method="GET", **kwargs): # Amazon's MWS does not allow such a thing. extra_data = remove_empty(extra_data) - # convert all Python date/time objects to isoformat - for key, value in extra_data.items(): - if isinstance(value, (datetime.datetime, datetime.date)): - extra_data[key] = value.isoformat() + extra_data = clean_extra_data(extra_data) params = self.get_default_params() proxies = self.get_proxies() @@ -279,7 +300,8 @@ def make_request(self, extra_data, method="GET", **kwargs): # My answer is, here i have to get the url parsed string of params in order to sign it, so # if i pass the params dict as params to request, request will repeat that step because it will need # to convert the dict to a url parsed string, so why do it twice if i can just pass the full url :). - response = request(method, url, data=kwargs.get('body', ''), headers=headers, proxies=proxies) + response = request(method, url, data=kwargs.get( + 'body', ''), headers=headers, proxies=proxies) response.raise_for_status() # When retrieving data from the response object, # be aware that response.content returns the content in bytes while response.text calls diff --git a/tests/request_methods/test_outboundshipments.py b/tests/request_methods/test_outboundshipments.py index d7b4757b..9859fc50 100644 --- a/tests/request_methods/test_outboundshipments.py +++ b/tests/request_methods/test_outboundshipments.py @@ -11,6 +11,7 @@ class OutboundShipmentsTestCase(unittest.TestCase, CommonRequestTestTools): Test cases for OutboundShipments. """ # TODO: Add remaining methods for OutboundShipments + def setUp(self): self.api = mws.OutboundShipments( self.CREDENTIAL_ACCESS, diff --git a/tests/request_methods/test_reports.py b/tests/request_methods/test_reports.py index f64e68b2..ea5e2756 100644 --- a/tests/request_methods/test_reports.py +++ b/tests/request_methods/test_reports.py @@ -6,12 +6,22 @@ import mws from .utils import CommonRequestTestTools +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + + +def transform_date(date): + return quote(date.isoformat(), safe='-_.~') + class ReportsTestCase(unittest.TestCase, CommonRequestTestTools): """ Test cases for Reports. """ # TODO: Add remaining methods for Reports + def setUp(self): self.api = mws.Reports( self.CREDENTIAL_ACCESS, @@ -26,8 +36,8 @@ def test_request_report(self): RequestReport operation. """ report_type = '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_' - start_date = datetime.datetime.utcnow() - end_date = datetime.datetime.utcnow() + datetime.timedelta(hours=1) + start_date = datetime.datetime(2018, 4, 30, 22, 59, 59) + end_date = datetime.datetime(2018, 4, 30, 23, 59, 59) marketplace_ids = [ 'iQzBCmf1y3', 'wH9q0CiEMp', @@ -38,11 +48,12 @@ def test_request_report(self): end_date=end_date, marketplace_ids=marketplace_ids, ) + self.assert_common_params(params) self.assertEqual(params['Action'], 'RequestReport') self.assertEqual(params['ReportType'], report_type) - self.assertEqual(params['StartDate'], start_date.isoformat()) - self.assertEqual(params['EndDate'], end_date.isoformat()) + self.assertEqual(params['StartDate'], '2018-04-30T22%3A59%3A59') + self.assertEqual(params['EndDate'], '2018-04-30T23%3A59%3A59') self.assertEqual(params['MarketplaceIdList.Id.1'], marketplace_ids[0]) self.assertEqual(params['MarketplaceIdList.Id.2'], marketplace_ids[1]) @@ -75,9 +86,9 @@ def test_get_report_request_list(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetReportRequestList') - self.assertEqual(params['MaxCount'], max_count) - self.assertEqual(params['RequestedFromDate'], from_date.isoformat()) - self.assertEqual(params['RequestedToDate'], to_date.isoformat()) + self.assertEqual(params['MaxCount'], str(max_count)) + self.assertEqual(params['RequestedFromDate'], transform_date(from_date)) + self.assertEqual(params['RequestedToDate'], transform_date(to_date)) self.assertEqual(params['ReportRequestIdList.Id.1'], request_ids[0]) self.assertEqual(params['ReportRequestIdList.Id.2'], request_ids[1]) self.assertEqual(params['ReportTypeList.Type.1'], report_types[0]) @@ -127,8 +138,8 @@ def test_get_report_request_count(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetReportRequestCount') - self.assertEqual(params['RequestedFromDate'], from_date.isoformat()) - self.assertEqual(params['RequestedToDate'], to_date.isoformat()) + self.assertEqual(params['RequestedFromDate'], transform_date(from_date)) + self.assertEqual(params['RequestedToDate'], transform_date(to_date)) self.assertEqual(params['ReportTypeList.Type.1'], report_types[0]) self.assertEqual(params['ReportTypeList.Type.2'], report_types[1]) self.assertEqual(params['ReportProcessingStatusList.Status.1'], processing_statuses[0]) @@ -160,10 +171,10 @@ def test_get_report_list(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetReportList') - self.assertEqual(params['Acknowledged'], acknowledged) - self.assertEqual(params['AvailableFromDate'], from_date.isoformat()) - self.assertEqual(params['AvailableToDate'], to_date.isoformat()) - self.assertEqual(params['MaxCount'], max_count) + self.assertEqual(params['Acknowledged'], str(acknowledged)) + self.assertEqual(params['AvailableFromDate'], transform_date(from_date)) + self.assertEqual(params['AvailableToDate'], transform_date(to_date)) + self.assertEqual(params['MaxCount'], str(max_count)) self.assertEqual(params['ReportRequestIdList.Id.1'], request_ids[0]) self.assertEqual(params['ReportRequestIdList.Id.2'], request_ids[1]) self.assertEqual(params['ReportTypeList.Type.1'], report_types[0]) @@ -208,9 +219,9 @@ def test_get_report_count(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetReportCount') - self.assertEqual(params['Acknowledged'], acknowledged) - self.assertEqual(params['AvailableFromDate'], from_date.isoformat()) - self.assertEqual(params['AvailableToDate'], to_date.isoformat()) + self.assertEqual(params['Acknowledged'], str(acknowledged)) + self.assertEqual(params['AvailableFromDate'], transform_date(from_date)) + self.assertEqual(params['AvailableToDate'], transform_date(to_date)) self.assertEqual(params['ReportTypeList.Type.1'], report_types[0]) self.assertEqual(params['ReportTypeList.Type.2'], report_types[1]) From e87012bebaebce194377683ae65ceaa25330d213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Zafra=20G=C3=B3mez?= Date: Fri, 4 May 2018 18:03:12 +0200 Subject: [PATCH 02/19] Feeds example. Use of ".parsed" changed. (#66) * Feeds example. * Feeds example. Use of ".parsed" changed. --- docs/source/feeds.rst | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/docs/source/feeds.rst b/docs/source/feeds.rst index 31f3cd70..ec5fdc88 100644 --- a/docs/source/feeds.rst +++ b/docs/source/feeds.rst @@ -13,11 +13,11 @@ To build your own XML data you should use Amazon documentation about feed types access_key = 'accesskey' #replace with your access key seller_id = 'merchantid' #replace with your seller id secret_key = 'secretkey' #replace with your secret key - marketplace_usa = 'ATVPDKIKX0DER' + MWS_MARKETPLACE_ID = 'ATVPDKIKX0DER' feed = mws.Feeds(access_key, secret_key, seller_id, region='US') - print "### Product feed ###" + print("### Product feed ###") xml = """
@@ -54,10 +54,11 @@ To build your own XML data you should use Amazon documentation about feed types """ - response = feed.submit_feed(xml, "_POST_PRODUCT_DATA_", MSW_MARKETPLACE_ID).parsed - print response + response = feed.submit_feed(xml, "_POST_PRODUCT_DATA_", MWS_MARKETPLACE_ID) + print(response.parsed) - print "### Inventory feed ###" + + print("### Inventory feed ###") xml = """
@@ -74,11 +75,11 @@ To build your own XML data you should use Amazon documentation about feed types """ - response = feed.submit_feed(xml, "_POST_INVENTORY_AVAILABILITY_DATA_", MSW_MARKETPLACE_ID).parsed - print response + response = feed.submit_feed(xml, "_POST_INVENTORY_AVAILABILITY_DATA_", MWS_MARKETPLACE_ID) + print(response.parsed) - print "### Product image feed ###" + print("### Product image feed ###") xml = """
@@ -96,5 +97,5 @@ To build your own XML data you should use Amazon documentation about feed types """ - response = feed.submit_feed(xml, "_POST_PRODUCT_IMAGE_DATA_", MSW_MARKETPLACE_ID).parsed - print response \ No newline at end of file + response = feed.submit_feed(xml, "_POST_PRODUCT_IMAGE_DATA_", MWS_MARKETPLACE_ID) + print(response.parsed) From 456a9a0cad5df7fabfeefb4ee62153c321dca68d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sat, 5 May 2018 01:47:14 +0200 Subject: [PATCH 03/19] see conversation pull request --- mws/apis/subscriptions.py | 8 ++++-- mws/mws.py | 36 +++++++++++---------------- tests/request_methods/test_reports.py | 4 +++ 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/mws/apis/subscriptions.py b/mws/apis/subscriptions.py index 6bc5d930..7a5abd11 100644 --- a/mws/apis/subscriptions.py +++ b/mws/apis/subscriptions.py @@ -25,14 +25,18 @@ class Subscriptions(MWS): # This might cut down on some time setting up all the values for the destination for each call, # particularly if someone needs to make several calls at once for the same destination. - def register_destination(self): + def register_destination(self, marketplaceid, destination_uri): """ Specifies a new destination where you want to receive notifications. Docs: http://docs.developer.amazonservices.com/en_US/subscriptions/Subscriptions_RegisterDestination.html """ - raise NotImplementedError + data = dict(Action="RegisterDestination", MarketplaceId=marketplaceid) + data.update({'Destination.AttributeList.member.1.Key': 'sqsQueueUrl'}) + data.update({'Destination.AttributeList.member.1.Value': destination_uri}) + data.update({'Destination.DeliveryChannel': 'SQS'}) + return self.make_request(data, "POST") def deregister_destination(self): """ diff --git a/mws/mws.py b/mws/mws.py index 52a57c07..206d7ea5 100644 --- a/mws/mws.py +++ b/mws/mws.py @@ -57,15 +57,6 @@ class MWSError(Exception): response = None -class InputError(Exception): - def __init__(self, key, value, dtype): - self.message = 'the parameter: {}, expected a value of type {}'\ - ', got: {} with type {}'.format(key, dtype, value, type(value)) - - def __str__(self): - return self.message - - def calc_request_description(params): """ Returns a flatted string with the request description, built from the params dict. @@ -90,22 +81,24 @@ def calc_request_description(params): return '&'.join(description_items) -def remove_empty(dict_): - return {k: v for k, v in dict_.items() if v} - - def clean_extra_data(extra_data): + """Input cleanup and prevent a lot of common input mistakes.""" + # silently remove parameter where values are empty + extra_data = {k: v for k, v in extra_data.items() if v} + extra_data_enc = dict() for key, value in extra_data.items(): + if isinstance(value, (dict, list, set, tuple)): + message = 'expected string or datetime datatype, got {},'\ + 'for key {} and value {}'.format( + type(value), key, str(value)) + raise MWSError(message) if isinstance(value, (datetime.datetime, datetime.date)): - value = str(value.isoformat()) - if isinstance(value, (bool, int)): - value = str(value) - try: - value.lower() + value + '' - except: - """final validation, value not like a string""" - raise InputError(key, value, str) + value = value.isoformat() + if isinstance(value, bool): + value = str(value).lower() + value = str(value) + extra_data_enc[key] = quote(value, safe='-_.~') return extra_data_enc @@ -272,7 +265,6 @@ def make_request(self, extra_data, method="GET", **kwargs): """ # Remove all keys with an empty value because # Amazon's MWS does not allow such a thing. - extra_data = remove_empty(extra_data) extra_data = clean_extra_data(extra_data) diff --git a/tests/request_methods/test_reports.py b/tests/request_methods/test_reports.py index ea5e2756..879079c3 100644 --- a/tests/request_methods/test_reports.py +++ b/tests/request_methods/test_reports.py @@ -16,6 +16,10 @@ def transform_date(date): return quote(date.isoformat(), safe='-_.~') +def transform_bool(b): + return str(b).lower() + + class ReportsTestCase(unittest.TestCase, CommonRequestTestTools): """ Test cases for Reports. From 71215f563b1d981260bcdbca24d3a025c1fa0ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sat, 5 May 2018 03:13:26 +0200 Subject: [PATCH 04/19] modified tests to fit new clean method --- .pytest_cache/v/cache/lastfailed | 1 + .pytest_cache/v/cache/nodeids | 111 +++++++++++++ tests/request_methods/test_feeds.py | 24 ++- tests/request_methods/test_finances.py | 28 ++-- .../request_methods/test_inboundshipments.py | 150 +++++++++++++----- tests/request_methods/test_inventory.py | 13 +- tests/request_methods/test_orders.py | 30 ++-- tests/request_methods/test_products.py | 60 ++++--- tests/request_methods/test_recommendations.py | 13 +- tests/request_methods/test_reports.py | 4 +- 10 files changed, 335 insertions(+), 99 deletions(-) create mode 100644 .pytest_cache/v/cache/lastfailed create mode 100644 .pytest_cache/v/cache/nodeids diff --git a/.pytest_cache/v/cache/lastfailed b/.pytest_cache/v/cache/lastfailed new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/.pytest_cache/v/cache/lastfailed @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/.pytest_cache/v/cache/nodeids b/.pytest_cache/v/cache/nodeids new file mode 100644 index 00000000..857a9eea --- /dev/null +++ b/.pytest_cache/v/cache/nodeids @@ -0,0 +1,111 @@ +[ + "tests/request_methods/test_feeds.py::FeedsTestCase::test_cancel_feed_submissions", + "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_count", + "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_list", + "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_list_by_next_token", + "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_list_by_next_token_alias", + "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_result", + "tests/request_methods/test_feeds.py::FeedsTestCase::test_service_status", + "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_event_groups", + "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_event_groups_by_next_token", + "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_event_groups_by_next_token_alias", + "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_events", + "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_events_by_next_token", + "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_events_by_next_token_alias", + "tests/request_methods/test_finances.py::FinancesTestCase::test_service_status", + "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_args_built_CreateInboundShipmentPlan", + "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_args_built_other_operation", + "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_empty_args_list", + "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_item_not_a_dict", + "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_required_keys_missing_CreateInboundShipmentPlan", + "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_required_keys_missing_other_operation", + "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_address_empty_raises_exception", + "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_address_not_dict_raises_exception", + "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_full_address_built_properly", + "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_partial_address_built_properly", + "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_required_keys_missing", + "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_set_address_with_constructor", + "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_create_inbound_shipment", + "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_create_inbound_shipment_exceptions", + "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_create_inbound_shipment_plan", + "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_create_inbound_shipment_plan_exceptions", + "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_service_status", + "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_update_inbound_shipment", + "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_update_inbound_shipment_exceptions", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_confirm_preorder", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_confirm_transport_request", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_estimate_transport_request", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_bill_of_lading", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_inbound_guidance_for_asin", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_inbound_guidance_for_sku", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_package_labels", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_pallet_labels", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_preorder_info", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_prep_instructions_for_asin", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_prep_instructions_for_sku", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_transport_content", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_unique_package_labels", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipment_items", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipment_items_by_next_token", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipment_items_by_next_token_alias", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipments", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipments_by_next_token", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipments_by_next_token_alias", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_service_status", + "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_void_transport_request", + "tests/request_methods/test_inventory.py::InventoryTestCase::test_list_inventory_supply", + "tests/request_methods/test_inventory.py::InventoryTestCase::test_list_inventory_supply_by_next_token", + "tests/request_methods/test_inventory.py::InventoryTestCase::test_list_inventory_supply_by_next_token_alias", + "tests/request_methods/test_inventory.py::InventoryTestCase::test_service_status", + "tests/request_methods/test_merchantfulfillment.py::MerchantFulfillmentTestCase::test_cancel_shipment", + "tests/request_methods/test_merchantfulfillment.py::MerchantFulfillmentTestCase::test_get_shipment", + "tests/request_methods/test_merchantfulfillment.py::MerchantFulfillmentTestCase::test_service_status", + "tests/request_methods/test_orders.py::OrdersTestCase::test_get_order", + "tests/request_methods/test_orders.py::OrdersTestCase::test_list_order_items", + "tests/request_methods/test_orders.py::OrdersTestCase::test_list_order_items_by_next_token", + "tests/request_methods/test_orders.py::OrdersTestCase::test_list_order_items_by_next_token_alias", + "tests/request_methods/test_orders.py::OrdersTestCase::test_list_orders", + "tests/request_methods/test_orders.py::OrdersTestCase::test_list_orders_by_next_token", + "tests/request_methods/test_orders.py::OrdersTestCase::test_list_orders_by_next_token_alias", + "tests/request_methods/test_orders.py::OrdersTestCase::test_service_status", + "tests/request_methods/test_outboundshipments.py::OutboundShipmentsTestCase::test_service_status", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_competitive_pricing_for_asin", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_competitive_pricing_for_sku", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_lowest_offer_listings_for_asin", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_lowest_offer_listings_for_sku", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_lowest_priced_offers_for_asin", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_lowest_priced_offers_for_sku", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_matching_product", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_matching_product_for_id", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_my_price_for_asin", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_my_price_for_sku", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_product_categories_for_asin", + "tests/request_methods/test_products.py::ProductsTestCase::test_get_product_categories_for_sku", + "tests/request_methods/test_products.py::ProductsTestCase::test_list_matching_products", + "tests/request_methods/test_products.py::ProductsTestCase::test_service_status", + "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_get_last_updated_time_for_recommendations", + "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_list_recommendations", + "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_list_recommendations_by_next_token", + "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_list_recommendations_by_next_token_alias", + "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_service_status", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_count", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_list", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_list_by_next_token", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_list_by_next_token_alias", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_request_count", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_request_list", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_request_list_by_next_token", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_request_list_by_next_token_alias", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_schedule_count", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_schedule_list", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_schedule_list_by_next_token", + "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_schedule_list_by_next_token_alias", + "tests/request_methods/test_reports.py::ReportsTestCase::test_request_report", + "tests/request_methods/test_reports.py::ReportsTestCase::test_service_status", + "tests/request_methods/test_sellers.py::SellersTestCase::test_list_marketplace_participations", + "tests/request_methods/test_sellers.py::SellersTestCase::test_list_marketplace_participations_by_next_token", + "tests/request_methods/test_sellers.py::SellersTestCase::test_list_marketplace_participations_by_next_token_alias", + "tests/request_methods/test_sellers.py::SellersTestCase::test_service_status", + "tests/request_methods/test_subscriptions.py::SubscriptionsTestCase::test_service_status" +] \ No newline at end of file diff --git a/tests/request_methods/test_feeds.py b/tests/request_methods/test_feeds.py index 736f128b..78491717 100644 --- a/tests/request_methods/test_feeds.py +++ b/tests/request_methods/test_feeds.py @@ -6,12 +6,22 @@ import mws from .utils import CommonRequestTestTools +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + + +def transform_date(date): + return quote(date.isoformat(), safe='-_.~') + class FeedsTestCase(unittest.TestCase, CommonRequestTestTools): """ Test cases for Feeds. """ # TODO: Add remaining methods for Feeds + def setUp(self): self.api = mws.Feeds( self.CREDENTIAL_ACCESS, @@ -33,9 +43,9 @@ def test_get_feed_submission_list(self): GetFeedSubmissionList operation """ from_date = datetime.datetime.utcnow() - from_date_stamp = from_date.isoformat() + from_date_stamp = transform_date(from_date) to_date = datetime.datetime.utcnow() - to_date_stamp = to_date.isoformat() + to_date_stamp = transform_date(to_date) feed_ids = [ '1058369303', '1228369302', @@ -61,7 +71,7 @@ def test_get_feed_submission_list(self): self.assertEqual(params['Action'], 'GetFeedSubmissionList') self.assertEqual(params['SubmittedFromDate'], from_date_stamp) self.assertEqual(params['SubmittedToDate'], to_date_stamp) - self.assertEqual(params['MaxCount'], max_count) + self.assertEqual(params['MaxCount'], str(max_count)) self.assertEqual(params['FeedSubmissionIdList.Id.1'], feed_ids[0]) self.assertEqual(params['FeedSubmissionIdList.Id.2'], feed_ids[1]) self.assertEqual(params['FeedTypeList.Type.1'], feed_types[0]) @@ -94,9 +104,9 @@ def test_get_feed_submission_count(self): GetFeedSubmissionCount operation """ from_date = datetime.datetime.utcnow() - from_date_stamp = from_date.isoformat() + from_date_stamp = transform_date(from_date) to_date = datetime.datetime.utcnow() - to_date_stamp = to_date.isoformat() + to_date_stamp = transform_date(to_date) feed_types = [ '_POST_PRODUCT_OVERRIDES_DATA_', '_POST_FLAT_FILE_FULFILLMENT_ORDER_CANCELLATION_REQUEST_DATA_', @@ -125,9 +135,9 @@ def test_cancel_feed_submissions(self): CancelFeedSubmissions operation """ from_date = datetime.datetime.utcnow() - from_date_stamp = from_date.isoformat() + from_date_stamp = transform_date(from_date) to_date = datetime.datetime.utcnow() - to_date_stamp = to_date.isoformat() + to_date_stamp = transform_date(to_date) feed_ids = [ 'SUB63kvutS', 'l8dM04jxGD', diff --git a/tests/request_methods/test_finances.py b/tests/request_methods/test_finances.py index 1724e8ba..eb87957c 100644 --- a/tests/request_methods/test_finances.py +++ b/tests/request_methods/test_finances.py @@ -6,12 +6,22 @@ import mws from .utils import CommonRequestTestTools +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + + +def transform_date(date): + return quote(date.isoformat(), safe='-_.~') + class FinancesTestCase(unittest.TestCase, CommonRequestTestTools): """ Test cases for Finances. """ # TODO: Add remaining methods for Finances + def setUp(self): self.api = mws.Finances( self.CREDENTIAL_ACCESS, @@ -26,9 +36,7 @@ def test_list_financial_event_groups(self): ListFinancialEventGroups operation. """ created_after = datetime.datetime.utcnow() - created_after_stamp = created_after.isoformat() created_before = datetime.datetime.utcnow() - created_before_stamp = created_before.isoformat() max_results = 659 params = self.api.list_financial_event_groups( created_after=created_after, @@ -37,9 +45,11 @@ def test_list_financial_event_groups(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'ListFinancialEventGroups') - self.assertEqual(params['FinancialEventGroupStartedAfter'], created_after_stamp) - self.assertEqual(params['FinancialEventGroupStartedBefore'], created_before_stamp) - self.assertEqual(params['MaxResultsPerPage'], max_results) + self.assertEqual(params['FinancialEventGroupStartedAfter'], + transform_date(created_after)) + self.assertEqual(params['FinancialEventGroupStartedBefore'], + transform_date(created_before)) + self.assertEqual(params['MaxResultsPerPage'], str(max_results)) def test_list_financial_event_groups_by_next_token(self): """ @@ -66,9 +76,7 @@ def test_list_financial_events(self): ListFinancialEvents operation. """ posted_after = datetime.datetime.utcnow() - posted_after_stamp = posted_after.isoformat() posted_before = datetime.datetime.utcnow() - posted_before_stamp = posted_before.isoformat() amazon_order_id = '123-4567890-1234567' financial_event_group_id = '22YgYW55IGNhcm5hbCBwbGVhEXAMPLE' max_results = 156 @@ -83,9 +91,9 @@ def test_list_financial_events(self): self.assertEqual(params['Action'], 'ListFinancialEvents') self.assertEqual(params['FinancialEventGroupId'], financial_event_group_id) self.assertEqual(params['AmazonOrderId'], amazon_order_id) - self.assertEqual(params['PostedAfter'], posted_after_stamp) - self.assertEqual(params['PostedBefore'], posted_before_stamp) - self.assertEqual(params['MaxResultsPerPage'], max_results) + self.assertEqual(params['PostedAfter'], transform_date(posted_after)) + self.assertEqual(params['PostedBefore'], transform_date(posted_before)) + self.assertEqual(params['MaxResultsPerPage'], str(max_results)) def test_list_financial_events_by_next_token(self): """ diff --git a/tests/request_methods/test_inboundshipments.py b/tests/request_methods/test_inboundshipments.py index eb78d766..de367e54 100644 --- a/tests/request_methods/test_inboundshipments.py +++ b/tests/request_methods/test_inboundshipments.py @@ -8,11 +8,29 @@ from mws.mws import MWSError from .utils import CommonRequestTestTools +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + + +def transform_date(date): + return quote(date.isoformat(), safe='-_.~') + + +def transform_string(s): + return quote(s, safe='-_.~') + + +def transform_bool(b): + return str(b).lower() + class ParseItemArgsTestCase(unittest.TestCase): """ Test cases that ensure `parse_item_args` raises exceptions where appropriate. """ + def test_empty_args_list(self): """ Should raise `MWSError` for an empty set of arguments. @@ -154,6 +172,7 @@ class SetShipFromAddressTestCase(unittest.TestCase): """ Test case covering msw.InboundShipments.set_ship_from_address """ + def setUp(self): self.inbound = mws.InboundShipments('', '', '') @@ -279,6 +298,7 @@ class FBAShipmentHandlingTestCase(unittest.TestCase, CommonRequestTestTools): Test cases for InboundShipments involving FBA shipment handling. These cases require `from_address` to be set, while others do not. """ + def setUp(self): self.addr = { 'name': 'Roland Deschain', @@ -331,18 +351,24 @@ def test_create_inbound_shipment_plan(self): self.assert_common_params(params) self.assertEqual(params['Action'], 'CreateInboundShipmentPlan') self.assertEqual(params['ShipToCountryCode'], country_code) - self.assertEqual(params['ShipToCountrySubdivisionCode'], subdivision_code) + self.assertEqual(params['ShipToCountrySubdivisionCode'], transform_string(subdivision_code)) self.assertEqual(params['LabelPrepPreference'], label_preference) # from_address expanded - self.assertEqual(params['ShipFromAddress.Name'], self.addr['name']) - self.assertEqual(params['ShipFromAddress.AddressLine1'], self.addr['address_1']) - self.assertEqual(params['ShipFromAddress.City'], self.addr['city']) - self.assertEqual(params['ShipFromAddress.CountryCode'], self.addr['country']) + self.assertEqual(params['ShipFromAddress.Name'], transform_string(self.addr['name'])) + self.assertEqual(params['ShipFromAddress.AddressLine1'], + transform_string(self.addr['address_1'])) + self.assertEqual(params['ShipFromAddress.City'], transform_string(self.addr['city'])) + self.assertEqual(params['ShipFromAddress.CountryCode'], + transform_string(self.addr['country'])) # item data - self.assertEqual(params['InboundShipmentPlanRequestItems.member.1.SellerSKU'], items[0]['sku']) - self.assertEqual(params['InboundShipmentPlanRequestItems.member.1.Quantity'], items[0]['quantity']) - self.assertEqual(params['InboundShipmentPlanRequestItems.member.2.SellerSKU'], items[1]['sku']) - self.assertEqual(params['InboundShipmentPlanRequestItems.member.2.Quantity'], items[1]['quantity']) + self.assertEqual( + params['InboundShipmentPlanRequestItems.member.1.SellerSKU'], items[0]['sku']) + self.assertEqual( + params['InboundShipmentPlanRequestItems.member.1.Quantity'], str(items[0]['quantity'])) + self.assertEqual( + params['InboundShipmentPlanRequestItems.member.2.SellerSKU'], items[1]['sku']) + self.assertEqual( + params['InboundShipmentPlanRequestItems.member.2.Quantity'], str(items[1]['quantity'])) def test_create_inbound_shipment_exceptions(self): """ @@ -411,22 +437,35 @@ def test_create_inbound_shipment(self): self.assert_common_params(params) self.assertEqual(params['Action'], 'CreateInboundShipment') self.assertEqual(params['ShipmentId'], shipment_id) - self.assertEqual(params['InboundShipmentHeader.ShipmentName'], shipment_name) - self.assertEqual(params['InboundShipmentHeader.DestinationFulfillmentCenterId'], destination) + self.assertEqual(params['InboundShipmentHeader.ShipmentName'], + transform_string(shipment_name)) + self.assertEqual( + params['InboundShipmentHeader.DestinationFulfillmentCenterId'], destination) self.assertEqual(params['InboundShipmentHeader.LabelPrepPreference'], label_preference) - self.assertEqual(params['InboundShipmentHeader.AreCasesRequired'], case_required) + self.assertEqual(params['InboundShipmentHeader.AreCasesRequired'], + transform_bool(case_required)) self.assertEqual(params['InboundShipmentHeader.ShipmentStatus'], shipment_status) - self.assertEqual(params['InboundShipmentHeader.IntendedBoxContentsSource'], box_contents_source) + self.assertEqual( + params['InboundShipmentHeader.IntendedBoxContentsSource'], box_contents_source) # from_address - self.assertEqual(params['InboundShipmentHeader.ShipFromAddress.Name'], self.addr['name']) - self.assertEqual(params['InboundShipmentHeader.ShipFromAddress.AddressLine1'], self.addr['address_1']) - self.assertEqual(params['InboundShipmentHeader.ShipFromAddress.City'], self.addr['city']) - self.assertEqual(params['InboundShipmentHeader.ShipFromAddress.CountryCode'], self.addr['country']) + self.assertEqual(params['InboundShipmentHeader.ShipFromAddress.Name'], + transform_string(self.addr['name'])) + self.assertEqual( + params['InboundShipmentHeader.ShipFromAddress.AddressLine1'], + transform_string(self.addr['address_1'])) + self.assertEqual( + params['InboundShipmentHeader.ShipFromAddress.City'], + transform_string(self.addr['city'])) + self.assertEqual( + params['InboundShipmentHeader.ShipFromAddress.CountryCode'], + transform_string(self.addr['country'])) # item data self.assertEqual(params['InboundShipmentItems.member.1.SellerSKU'], items[0]['sku']) - self.assertEqual(params['InboundShipmentItems.member.1.QuantityShipped'], items[0]['quantity']) + self.assertEqual( + params['InboundShipmentItems.member.1.QuantityShipped'], str(items[0]['quantity'])) self.assertEqual(params['InboundShipmentItems.member.2.SellerSKU'], items[1]['sku']) - self.assertEqual(params['InboundShipmentItems.member.2.QuantityShipped'], items[1]['quantity']) + self.assertEqual( + params['InboundShipmentItems.member.2.QuantityShipped'], str(items[1]['quantity'])) def test_update_inbound_shipment_exceptions(self): """ @@ -488,22 +527,35 @@ def test_update_inbound_shipment(self): self.assert_common_params(params_1) self.assertEqual(params_1['Action'], 'UpdateInboundShipment') self.assertEqual(params_1['ShipmentId'], shipment_id) - self.assertEqual(params_1['InboundShipmentHeader.ShipmentName'], shipment_name) - self.assertEqual(params_1['InboundShipmentHeader.DestinationFulfillmentCenterId'], destination) + self.assertEqual(params_1['InboundShipmentHeader.ShipmentName'], + transform_string(shipment_name)) + self.assertEqual( + params_1['InboundShipmentHeader.DestinationFulfillmentCenterId'], destination) self.assertEqual(params_1['InboundShipmentHeader.LabelPrepPreference'], label_preference) - self.assertEqual(params_1['InboundShipmentHeader.AreCasesRequired'], case_required) + self.assertEqual(params_1['InboundShipmentHeader.AreCasesRequired'], + transform_bool(case_required)) self.assertEqual(params_1['InboundShipmentHeader.ShipmentStatus'], shipment_status) - self.assertEqual(params_1['InboundShipmentHeader.IntendedBoxContentsSource'], box_contents_source) + self.assertEqual( + params_1['InboundShipmentHeader.IntendedBoxContentsSource'], box_contents_source) # from_address - self.assertEqual(params_1['InboundShipmentHeader.ShipFromAddress.Name'], self.addr['name']) - self.assertEqual(params_1['InboundShipmentHeader.ShipFromAddress.AddressLine1'], self.addr['address_1']) - self.assertEqual(params_1['InboundShipmentHeader.ShipFromAddress.City'], self.addr['city']) - self.assertEqual(params_1['InboundShipmentHeader.ShipFromAddress.CountryCode'], self.addr['country']) + self.assertEqual( + params_1['InboundShipmentHeader.ShipFromAddress.Name'], + transform_string(self.addr['name'])) + self.assertEqual( + params_1['InboundShipmentHeader.ShipFromAddress.AddressLine1'], + transform_string(self.addr['address_1'])) + self.assertEqual( + params_1['InboundShipmentHeader.ShipFromAddress.City'], + transform_string(self.addr['city'])) + self.assertEqual( + params_1['InboundShipmentHeader.ShipFromAddress.CountryCode'], self.addr['country']) # item data self.assertEqual(params_1['InboundShipmentItems.member.1.SellerSKU'], items[0]['sku']) - self.assertEqual(params_1['InboundShipmentItems.member.1.QuantityShipped'], items[0]['quantity']) + self.assertEqual( + params_1['InboundShipmentItems.member.1.QuantityShipped'], str(items[0]['quantity'])) self.assertEqual(params_1['InboundShipmentItems.member.2.SellerSKU'], items[1]['sku']) - self.assertEqual(params_1['InboundShipmentItems.member.2.QuantityShipped'], items[1]['quantity']) + self.assertEqual( + params_1['InboundShipmentItems.member.2.QuantityShipped'], str(items[1]['quantity'])) # Additional case: no items required. Params should have no Items keys if not provided params_2 = self.api.update_inbound_shipment( shipment_id=shipment_id, @@ -517,17 +569,26 @@ def test_update_inbound_shipment(self): self.assert_common_params(params_1) self.assertEqual(params_2['Action'], 'UpdateInboundShipment') self.assertEqual(params_2['ShipmentId'], shipment_id) - self.assertEqual(params_2['InboundShipmentHeader.ShipmentName'], shipment_name) - self.assertEqual(params_2['InboundShipmentHeader.DestinationFulfillmentCenterId'], destination) + self.assertEqual(params_2['InboundShipmentHeader.ShipmentName'], + transform_string(shipment_name)) + self.assertEqual( + params_2['InboundShipmentHeader.DestinationFulfillmentCenterId'], destination) self.assertEqual(params_2['InboundShipmentHeader.LabelPrepPreference'], label_preference) - self.assertEqual(params_2['InboundShipmentHeader.AreCasesRequired'], case_required) + self.assertEqual(params_2['InboundShipmentHeader.AreCasesRequired'], + transform_bool(case_required)) self.assertEqual(params_2['InboundShipmentHeader.ShipmentStatus'], shipment_status) - self.assertEqual(params_2['InboundShipmentHeader.IntendedBoxContentsSource'], box_contents_source) + self.assertEqual( + params_2['InboundShipmentHeader.IntendedBoxContentsSource'], box_contents_source) # from_address - self.assertEqual(params_2['InboundShipmentHeader.ShipFromAddress.Name'], self.addr['name']) - self.assertEqual(params_2['InboundShipmentHeader.ShipFromAddress.AddressLine1'], self.addr['address_1']) - self.assertEqual(params_2['InboundShipmentHeader.ShipFromAddress.City'], self.addr['city']) - self.assertEqual(params_2['InboundShipmentHeader.ShipFromAddress.CountryCode'], self.addr['country']) + self.assertEqual(params_2['InboundShipmentHeader.ShipFromAddress.Name'], + transform_string(self.addr['name'])) + self.assertEqual( + params_2['InboundShipmentHeader.ShipFromAddress.AddressLine1'], + transform_string(self.addr['address_1'])) + self.assertEqual(params_2['InboundShipmentHeader.ShipFromAddress.City'], + transform_string(self.addr['city'])) + self.assertEqual( + params_2['InboundShipmentHeader.ShipFromAddress.CountryCode'], self.addr['country']) # items keys should not be present param_item_keys = [x for x in params_2.keys() if x.startswith('InboundShipmentItems')] # list should be empty, because no keys should be present @@ -539,6 +600,7 @@ class InboundShipmentsRequestsTestCase(unittest.TestCase, CommonRequestTestTools Test cases for InboundShipments requests that do not involve FBA shipment handling and do not require `from_address` to be set. """ + def setUp(self): self.api = mws.InboundShipments( self.CREDENTIAL_ACCESS, @@ -631,7 +693,7 @@ def test_confirm_preorder(self): self.assert_common_params(params) self.assertEqual(params['Action'], 'ConfirmPreorder') self.assertEqual(params['ShipmentId'], shipment_id) - self.assertEqual(params['NeedByDate'], need_by_date.isoformat()) + self.assertEqual(params['NeedByDate'], transform_date(need_by_date)) def test_get_prep_instructions_for_sku(self): """ @@ -777,7 +839,7 @@ def test_get_package_labels(self): self.assertEqual(params['Action'], 'GetPackageLabels') self.assertEqual(params['ShipmentId'], shipment_id) self.assertEqual(params['PageType'], page_type) - self.assertEqual(params['NumberOfPackages'], num_labels) + self.assertEqual(params['NumberOfPackages'], str(num_labels)) def test_get_unique_package_labels(self): """ @@ -830,7 +892,7 @@ def test_get_pallet_labels(self): self.assertEqual(params['Action'], 'GetPalletLabels') self.assertEqual(params['ShipmentId'], shipment_id) self.assertEqual(params['PageType'], page_type) - self.assertEqual(params['NumberOfPallets'], num_labels) + self.assertEqual(params['NumberOfPallets'], str(num_labels)) def test_get_bill_of_lading(self): """ @@ -866,8 +928,8 @@ def test_list_inbound_shipments(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'ListInboundShipments') - self.assertEqual(params['LastUpdatedBefore'], last_updated_before.isoformat()) - self.assertEqual(params['LastUpdatedAfter'], last_updated_after.isoformat()) + self.assertEqual(params['LastUpdatedBefore'], transform_date(last_updated_before)) + self.assertEqual(params['LastUpdatedAfter'], transform_date(last_updated_after)) self.assertEqual(params['ShipmentStatusList.member.1'], shipment_statuses[0]) self.assertEqual(params['ShipmentStatusList.member.2'], shipment_statuses[1]) self.assertEqual(params['ShipmentIdList.member.1'], shipment_ids[0]) @@ -908,8 +970,8 @@ def test_list_inbound_shipment_items(self): self.assert_common_params(params) self.assertEqual(params['Action'], 'ListInboundShipmentItems') self.assertEqual(params['ShipmentId'], shipment_id) - self.assertEqual(params['LastUpdatedBefore'], last_updated_before.isoformat()) - self.assertEqual(params['LastUpdatedAfter'], last_updated_after.isoformat()) + self.assertEqual(params['LastUpdatedBefore'], transform_date(last_updated_before)) + self.assertEqual(params['LastUpdatedAfter'], transform_date(last_updated_after)) def test_list_inbound_shipment_items_by_next_token(self): """ diff --git a/tests/request_methods/test_inventory.py b/tests/request_methods/test_inventory.py index 59a9d9a1..b9c0ff29 100644 --- a/tests/request_methods/test_inventory.py +++ b/tests/request_methods/test_inventory.py @@ -6,11 +6,21 @@ import mws from .utils import CommonRequestTestTools +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + + +def transform_date(date): + return quote(date.isoformat(), safe='-_.~') + class InventoryTestCase(unittest.TestCase, CommonRequestTestTools): """ Test cases for Inventory. """ + def setUp(self): self.api = mws.Inventory( self.CREDENTIAL_ACCESS, @@ -25,13 +35,12 @@ def test_list_inventory_supply(self): ListInventorySupply operation """ now = datetime.datetime.utcnow() - now_timestamp = now.isoformat() skus = ['thing1', 'thing2'] response_group = 'Detailed' params = self.api.list_inventory_supply(skus, now, response_group=response_group) self.assert_common_params(params) self.assertEqual(params['Action'], 'ListInventorySupply') - self.assertEqual(params['QueryStartDateTime'], now_timestamp) + self.assertEqual(params['QueryStartDateTime'], transform_date(now)) self.assertEqual(params['ResponseGroup'], 'Detailed') self.assertEqual(params['SellerSkus.member.1'], 'thing1') self.assertEqual(params['SellerSkus.member.2'], 'thing2') diff --git a/tests/request_methods/test_orders.py b/tests/request_methods/test_orders.py index 1b2a72b0..4f9a8385 100644 --- a/tests/request_methods/test_orders.py +++ b/tests/request_methods/test_orders.py @@ -6,12 +6,26 @@ import mws from .utils import CommonRequestTestTools +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + + +def transform_date(date): + return quote(date.isoformat(), safe='-_.~') + + +def transform_bool(b): + return str(b).lower() + class OrdersTestCase(unittest.TestCase, CommonRequestTestTools): """ Test cases for Orders. """ # TODO: Add remaining methods for Orders + def setUp(self): self.api = mws.Orders( self.CREDENTIAL_ACCESS, @@ -26,13 +40,9 @@ def test_list_orders(self): ListOrders operation. """ created_after = datetime.datetime.utcnow() - created_after_stamp = created_after.isoformat() created_before = datetime.datetime.utcnow() + datetime.timedelta(hours=1) - created_before_stamp = created_before.isoformat() last_updated_after = datetime.datetime.utcnow() + datetime.timedelta(hours=2) - last_updated_after_stamp = last_updated_after.isoformat() last_updated_before = datetime.datetime.utcnow() + datetime.timedelta(hours=3) - last_updated_before_stamp = last_updated_before.isoformat() max_results = 83 marketplace_ids = [ 'DV1t7ZOrjM', @@ -72,13 +82,13 @@ def test_list_orders(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'ListOrders') - self.assertEqual(params['CreatedAfter'], created_after_stamp) - self.assertEqual(params['CreatedBefore'], created_before_stamp) - self.assertEqual(params['LastUpdatedAfter'], last_updated_after_stamp) - self.assertEqual(params['LastUpdatedBefore'], last_updated_before_stamp) - self.assertEqual(params['BuyerEmail'], buyer_email) + self.assertEqual(params['CreatedAfter'], transform_date(created_after)) + self.assertEqual(params['CreatedBefore'], transform_date(created_before)) + self.assertEqual(params['LastUpdatedAfter'], transform_date(last_updated_after)) + self.assertEqual(params['LastUpdatedBefore'], transform_date(last_updated_before)) + self.assertEqual(params['BuyerEmail'], 'dudley.do.right%40example.com') self.assertEqual(params['SellerOrderId'], seller_order_id) - self.assertEqual(params['MaxResultsPerPage'], max_results) + self.assertEqual(params['MaxResultsPerPage'], str(max_results)) self.assertEqual(params['OrderStatus.Status.1'], order_statuses[0]) self.assertEqual(params['OrderStatus.Status.2'], order_statuses[1]) self.assertEqual(params['MarketplaceId.Id.1'], marketplace_ids[0]) diff --git a/tests/request_methods/test_products.py b/tests/request_methods/test_products.py index 57d55730..9c533aa5 100644 --- a/tests/request_methods/test_products.py +++ b/tests/request_methods/test_products.py @@ -5,12 +5,26 @@ import mws from .utils import CommonRequestTestTools +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + + +def transform_string(s): + return quote(s, safe='-_.~') + + +def transform_bool(b): + return str(b).lower() + class ProductsTestCase(unittest.TestCase, CommonRequestTestTools): """ Test cases for Products. """ # TODO: Add remaining methods for Products + def setUp(self): self.api = mws.Products( self.CREDENTIAL_ACCESS, @@ -34,8 +48,8 @@ def test_list_matching_products(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'ListMatchingProducts') - self.assertEqual(params['MarketplaceId'], marketplace_id) - self.assertEqual(params['Query'], query) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) + self.assertEqual(params['Query'], transform_string(query)) self.assertEqual(params['QueryContextId'], context_id) def test_get_matching_product(self): @@ -53,7 +67,7 @@ def test_get_matching_product(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetMatchingProduct') - self.assertEqual(params['MarketplaceId'], marketplace_id) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) self.assertEqual(params['ASINList.ASIN.1'], asins[0]) self.assertEqual(params['ASINList.ASIN.2'], asins[1]) @@ -74,7 +88,7 @@ def test_get_matching_product_for_id(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetMatchingProductForId') - self.assertEqual(params['MarketplaceId'], marketplace_id) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) self.assertEqual(params['IdType'], type_) self.assertEqual(params['IdList.Id.1'], ids[0]) self.assertEqual(params['IdList.Id.2'], ids[1]) @@ -94,7 +108,7 @@ def test_get_competitive_pricing_for_sku(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetCompetitivePricingForSKU') - self.assertEqual(params['MarketplaceId'], marketplace_id) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) self.assertEqual(params['SellerSKUList.SellerSKU.1'], skus[0]) self.assertEqual(params['SellerSKUList.SellerSKU.2'], skus[1]) @@ -113,7 +127,7 @@ def test_get_competitive_pricing_for_asin(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetCompetitivePricingForASIN') - self.assertEqual(params['MarketplaceId'], marketplace_id) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) self.assertEqual(params['ASINList.ASIN.1'], asins[0]) self.assertEqual(params['ASINList.ASIN.2'], asins[1]) @@ -137,11 +151,11 @@ def test_get_lowest_offer_listings_for_sku(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetLowestOfferListingsForSKU') - self.assertEqual(params['MarketplaceId'], marketplace_id) - self.assertEqual(params['ItemCondition'], condition) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) + self.assertEqual(params['ItemCondition'], transform_string(condition)) # TODO when this fails later after "clean" implemented, test against str conversion instead # (use commented `exclude_me_str` above) - self.assertEqual(params['ExcludeMe'], exclude_me) + self.assertEqual(params['ExcludeMe'], 'true') self.assertEqual(params['SellerSKUList.SellerSKU.1'], skus[0]) self.assertEqual(params['SellerSKUList.SellerSKU.2'], skus[1]) @@ -165,11 +179,11 @@ def test_get_lowest_offer_listings_for_asin(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetLowestOfferListingsForASIN') - self.assertEqual(params['MarketplaceId'], marketplace_id) - self.assertEqual(params['ItemCondition'], condition) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) + self.assertEqual(params['ItemCondition'], transform_string(condition)) # TODO when this fails later after "clean" implemented, test against str conversion instead # (use commented `exclude_me_str` above) - self.assertEqual(params['ExcludeMe'], exclude_me) + self.assertEqual(params['ExcludeMe'], transform_bool(exclude_me)) self.assertEqual(params['ASINList.ASIN.1'], asins[0]) self.assertEqual(params['ASINList.ASIN.2'], asins[1]) @@ -190,11 +204,11 @@ def test_get_lowest_priced_offers_for_sku(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetLowestPricedOffersForSKU') - self.assertEqual(params['MarketplaceId'], marketplace_id) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) self.assertEqual(params['ItemCondition'], condition) # TODO when this fails later after "clean" implemented, test against str conversion instead # (use commented `exclude_me_str` above) - self.assertEqual(params['ExcludeMe'], exclude_me) + self.assertEqual(params['ExcludeMe'], transform_bool(exclude_me)) self.assertEqual(params['SellerSKU'], sku) def test_get_lowest_priced_offers_for_asin(self): @@ -214,11 +228,11 @@ def test_get_lowest_priced_offers_for_asin(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetLowestPricedOffersForASIN') - self.assertEqual(params['MarketplaceId'], marketplace_id) - self.assertEqual(params['ItemCondition'], condition) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) + self.assertEqual(params['ItemCondition'], transform_string(condition)) # TODO when this fails later after "clean" implemented, test against str conversion instead # (use commented `exclude_me_str` above) - self.assertEqual(params['ExcludeMe'], exclude_me) + self.assertEqual(params['ExcludeMe'], 'true') self.assertEqual(params['ASIN'], asin) # def test_get_my_fees_estimate(self): @@ -244,8 +258,8 @@ def test_get_my_price_for_sku(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetMyPriceForSKU') - self.assertEqual(params['MarketplaceId'], marketplace_id) - self.assertEqual(params['ItemCondition'], condition) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) + self.assertEqual(params['ItemCondition'], transform_string(condition)) self.assertEqual(params['SellerSKUList.SellerSKU.1'], skus[0]) self.assertEqual(params['SellerSKUList.SellerSKU.2'], skus[1]) @@ -266,8 +280,8 @@ def test_get_my_price_for_asin(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetMyPriceForASIN') - self.assertEqual(params['MarketplaceId'], marketplace_id) - self.assertEqual(params['ItemCondition'], condition) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) + self.assertEqual(params['ItemCondition'], transform_string(condition)) self.assertEqual(params['ASINList.ASIN.1'], asins[0]) self.assertEqual(params['ASINList.ASIN.2'], asins[1]) @@ -283,7 +297,7 @@ def test_get_product_categories_for_sku(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetProductCategoriesForSKU') - self.assertEqual(params['MarketplaceId'], marketplace_id) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) self.assertEqual(params['SellerSKU'], sku) def test_get_product_categories_for_asin(self): @@ -298,5 +312,5 @@ def test_get_product_categories_for_asin(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetProductCategoriesForASIN') - self.assertEqual(params['MarketplaceId'], marketplace_id) + self.assertEqual(params['MarketplaceId'], transform_string(marketplace_id)) self.assertEqual(params['ASIN'], asin) diff --git a/tests/request_methods/test_recommendations.py b/tests/request_methods/test_recommendations.py index 3a049fc1..620f9f20 100644 --- a/tests/request_methods/test_recommendations.py +++ b/tests/request_methods/test_recommendations.py @@ -5,12 +5,22 @@ import mws from .utils import CommonRequestTestTools +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + + +def transform_string(s): + return quote(s, safe='-_.~') + class RecommendationsTestCase(unittest.TestCase, CommonRequestTestTools): """ Test cases for Recommendations. """ # TODO: Add remaining methods for Recommendations + def setUp(self): self.api = mws.Recommendations( self.CREDENTIAL_ACCESS, @@ -43,7 +53,8 @@ def test_list_recommendations(self): self.assert_common_params(params) self.assertEqual(params['Action'], 'ListRecommendations') self.assertEqual(params['MarketplaceId'], marketplace_id) - self.assertEqual(params['RecommendationCategory'], recommendation_category) + self.assertEqual(params['RecommendationCategory'], + transform_string(recommendation_category)) def test_list_recommendations_by_next_token(self): """ diff --git a/tests/request_methods/test_reports.py b/tests/request_methods/test_reports.py index 879079c3..c03be2ab 100644 --- a/tests/request_methods/test_reports.py +++ b/tests/request_methods/test_reports.py @@ -175,7 +175,7 @@ def test_get_report_list(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetReportList') - self.assertEqual(params['Acknowledged'], str(acknowledged)) + self.assertEqual(params['Acknowledged'], transform_bool(acknowledged)) self.assertEqual(params['AvailableFromDate'], transform_date(from_date)) self.assertEqual(params['AvailableToDate'], transform_date(to_date)) self.assertEqual(params['MaxCount'], str(max_count)) @@ -223,7 +223,7 @@ def test_get_report_count(self): ) self.assert_common_params(params) self.assertEqual(params['Action'], 'GetReportCount') - self.assertEqual(params['Acknowledged'], str(acknowledged)) + self.assertEqual(params['Acknowledged'], transform_bool(acknowledged)) self.assertEqual(params['AvailableFromDate'], transform_date(from_date)) self.assertEqual(params['AvailableToDate'], transform_date(to_date)) self.assertEqual(params['ReportTypeList.Type.1'], report_types[0]) From affb85f171931859964258e781534972b022c5f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sat, 5 May 2018 03:25:37 +0200 Subject: [PATCH 05/19] revert start in subapi --- mws/apis/subscriptions.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/mws/apis/subscriptions.py b/mws/apis/subscriptions.py index 7a5abd11..93fd9d7b 100644 --- a/mws/apis/subscriptions.py +++ b/mws/apis/subscriptions.py @@ -25,18 +25,14 @@ class Subscriptions(MWS): # This might cut down on some time setting up all the values for the destination for each call, # particularly if someone needs to make several calls at once for the same destination. - def register_destination(self, marketplaceid, destination_uri): + def register_destination(self): """ Specifies a new destination where you want to receive notifications. Docs: http://docs.developer.amazonservices.com/en_US/subscriptions/Subscriptions_RegisterDestination.html """ - data = dict(Action="RegisterDestination", MarketplaceId=marketplaceid) - data.update({'Destination.AttributeList.member.1.Key': 'sqsQueueUrl'}) - data.update({'Destination.AttributeList.member.1.Value': destination_uri}) - data.update({'Destination.DeliveryChannel': 'SQS'}) - return self.make_request(data, "POST") + raise NotImplementedError def deregister_destination(self): """ @@ -113,3 +109,4 @@ def update_subscription(self): http://docs.developer.amazonservices.com/en_US/subscriptions/Subscriptions_UpdateSubscription.html """ raise NotImplementedError + From 066787edd890d3ab71f10f3af24406d38a05add5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sat, 5 May 2018 03:30:00 +0200 Subject: [PATCH 06/19] git ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ee44e23a..ccfa7a14 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ develop-eggs pip-log.txt # Unit test / coverage reports +.pytest_cache .coverage .tox From b6202b0a6acb96be828a35a10ba9ad31c9b28b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sat, 5 May 2018 03:31:08 +0200 Subject: [PATCH 07/19] d --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ccfa7a14..0f58a6d5 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,7 @@ develop-eggs pip-log.txt # Unit test / coverage reports -.pytest_cache +.pytest_cache/ .coverage .tox From 9a879f5e4ab1e9a05379af2f1709f525828515f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sat, 5 May 2018 03:32:26 +0200 Subject: [PATCH 08/19] r --- .pytest_cache/v/cache/lastfailed | 1 - .pytest_cache/v/cache/nodeids | 111 ------------------------------- 2 files changed, 112 deletions(-) delete mode 100644 .pytest_cache/v/cache/lastfailed delete mode 100644 .pytest_cache/v/cache/nodeids diff --git a/.pytest_cache/v/cache/lastfailed b/.pytest_cache/v/cache/lastfailed deleted file mode 100644 index 9e26dfee..00000000 --- a/.pytest_cache/v/cache/lastfailed +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/.pytest_cache/v/cache/nodeids b/.pytest_cache/v/cache/nodeids deleted file mode 100644 index 857a9eea..00000000 --- a/.pytest_cache/v/cache/nodeids +++ /dev/null @@ -1,111 +0,0 @@ -[ - "tests/request_methods/test_feeds.py::FeedsTestCase::test_cancel_feed_submissions", - "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_count", - "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_list", - "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_list_by_next_token", - "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_list_by_next_token_alias", - "tests/request_methods/test_feeds.py::FeedsTestCase::test_get_feed_submission_result", - "tests/request_methods/test_feeds.py::FeedsTestCase::test_service_status", - "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_event_groups", - "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_event_groups_by_next_token", - "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_event_groups_by_next_token_alias", - "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_events", - "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_events_by_next_token", - "tests/request_methods/test_finances.py::FinancesTestCase::test_list_financial_events_by_next_token_alias", - "tests/request_methods/test_finances.py::FinancesTestCase::test_service_status", - "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_args_built_CreateInboundShipmentPlan", - "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_args_built_other_operation", - "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_empty_args_list", - "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_item_not_a_dict", - "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_required_keys_missing_CreateInboundShipmentPlan", - "tests/request_methods/test_inboundshipments.py::ParseItemArgsTestCase::test_required_keys_missing_other_operation", - "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_address_empty_raises_exception", - "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_address_not_dict_raises_exception", - "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_full_address_built_properly", - "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_partial_address_built_properly", - "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_required_keys_missing", - "tests/request_methods/test_inboundshipments.py::SetShipFromAddressTestCase::test_set_address_with_constructor", - "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_create_inbound_shipment", - "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_create_inbound_shipment_exceptions", - "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_create_inbound_shipment_plan", - "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_create_inbound_shipment_plan_exceptions", - "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_service_status", - "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_update_inbound_shipment", - "tests/request_methods/test_inboundshipments.py::FBAShipmentHandlingTestCase::test_update_inbound_shipment_exceptions", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_confirm_preorder", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_confirm_transport_request", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_estimate_transport_request", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_bill_of_lading", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_inbound_guidance_for_asin", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_inbound_guidance_for_sku", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_package_labels", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_pallet_labels", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_preorder_info", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_prep_instructions_for_asin", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_prep_instructions_for_sku", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_transport_content", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_get_unique_package_labels", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipment_items", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipment_items_by_next_token", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipment_items_by_next_token_alias", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipments", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipments_by_next_token", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_list_inbound_shipments_by_next_token_alias", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_service_status", - "tests/request_methods/test_inboundshipments.py::InboundShipmentsRequestsTestCase::test_void_transport_request", - "tests/request_methods/test_inventory.py::InventoryTestCase::test_list_inventory_supply", - "tests/request_methods/test_inventory.py::InventoryTestCase::test_list_inventory_supply_by_next_token", - "tests/request_methods/test_inventory.py::InventoryTestCase::test_list_inventory_supply_by_next_token_alias", - "tests/request_methods/test_inventory.py::InventoryTestCase::test_service_status", - "tests/request_methods/test_merchantfulfillment.py::MerchantFulfillmentTestCase::test_cancel_shipment", - "tests/request_methods/test_merchantfulfillment.py::MerchantFulfillmentTestCase::test_get_shipment", - "tests/request_methods/test_merchantfulfillment.py::MerchantFulfillmentTestCase::test_service_status", - "tests/request_methods/test_orders.py::OrdersTestCase::test_get_order", - "tests/request_methods/test_orders.py::OrdersTestCase::test_list_order_items", - "tests/request_methods/test_orders.py::OrdersTestCase::test_list_order_items_by_next_token", - "tests/request_methods/test_orders.py::OrdersTestCase::test_list_order_items_by_next_token_alias", - "tests/request_methods/test_orders.py::OrdersTestCase::test_list_orders", - "tests/request_methods/test_orders.py::OrdersTestCase::test_list_orders_by_next_token", - "tests/request_methods/test_orders.py::OrdersTestCase::test_list_orders_by_next_token_alias", - "tests/request_methods/test_orders.py::OrdersTestCase::test_service_status", - "tests/request_methods/test_outboundshipments.py::OutboundShipmentsTestCase::test_service_status", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_competitive_pricing_for_asin", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_competitive_pricing_for_sku", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_lowest_offer_listings_for_asin", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_lowest_offer_listings_for_sku", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_lowest_priced_offers_for_asin", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_lowest_priced_offers_for_sku", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_matching_product", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_matching_product_for_id", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_my_price_for_asin", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_my_price_for_sku", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_product_categories_for_asin", - "tests/request_methods/test_products.py::ProductsTestCase::test_get_product_categories_for_sku", - "tests/request_methods/test_products.py::ProductsTestCase::test_list_matching_products", - "tests/request_methods/test_products.py::ProductsTestCase::test_service_status", - "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_get_last_updated_time_for_recommendations", - "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_list_recommendations", - "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_list_recommendations_by_next_token", - "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_list_recommendations_by_next_token_alias", - "tests/request_methods/test_recommendations.py::RecommendationsTestCase::test_service_status", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_count", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_list", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_list_by_next_token", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_list_by_next_token_alias", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_request_count", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_request_list", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_request_list_by_next_token", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_request_list_by_next_token_alias", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_schedule_count", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_schedule_list", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_schedule_list_by_next_token", - "tests/request_methods/test_reports.py::ReportsTestCase::test_get_report_schedule_list_by_next_token_alias", - "tests/request_methods/test_reports.py::ReportsTestCase::test_request_report", - "tests/request_methods/test_reports.py::ReportsTestCase::test_service_status", - "tests/request_methods/test_sellers.py::SellersTestCase::test_list_marketplace_participations", - "tests/request_methods/test_sellers.py::SellersTestCase::test_list_marketplace_participations_by_next_token", - "tests/request_methods/test_sellers.py::SellersTestCase::test_list_marketplace_participations_by_next_token_alias", - "tests/request_methods/test_sellers.py::SellersTestCase::test_service_status", - "tests/request_methods/test_subscriptions.py::SubscriptionsTestCase::test_service_status" -] \ No newline at end of file From 881b7164a21296233ec9277eaae04e2eadb37e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sat, 5 May 2018 03:40:52 +0200 Subject: [PATCH 09/19] travis bugfix --- mws/apis/subscriptions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mws/apis/subscriptions.py b/mws/apis/subscriptions.py index 93fd9d7b..6bc5d930 100644 --- a/mws/apis/subscriptions.py +++ b/mws/apis/subscriptions.py @@ -109,4 +109,3 @@ def update_subscription(self): http://docs.developer.amazonservices.com/en_US/subscriptions/Subscriptions_UpdateSubscription.html """ raise NotImplementedError - From 4040f83f4ba1d8b6195be0c5e40a59492c19b44e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sat, 5 May 2018 03:59:38 +0200 Subject: [PATCH 10/19] call clean method for params too --- mws/mws.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mws/mws.py b/mws/mws.py index 206d7ea5..3777e2e3 100644 --- a/mws/mws.py +++ b/mws/mws.py @@ -75,6 +75,7 @@ def calc_request_description(params): "bar=4&baz=potato&foo=1" """ description_items = [] + params = clean_extra_data(params) for item in sorted(params.keys()): encoded_val = params[item] description_items.append('{}={}'.format(item, encoded_val)) From 7a8b7ae1754168f740df8c0f4d7bdee23a225fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sun, 6 May 2018 10:46:27 +0200 Subject: [PATCH 11/19] reuse modifiers for request params also it's helpful to understand how we modify params --- tests/request_methods/test_feeds.py | 11 +--------- tests/request_methods/test_finances.py | 11 +--------- .../request_methods/test_inboundshipments.py | 20 ++----------------- tests/request_methods/test_inventory.py | 11 +--------- tests/request_methods/test_orders.py | 15 +------------- tests/request_methods/test_products.py | 15 +------------- tests/request_methods/test_recommendations.py | 11 +--------- tests/request_methods/test_reports.py | 15 +------------- tests/request_methods/utils.py | 17 ++++++++++++++++ 9 files changed, 26 insertions(+), 100 deletions(-) diff --git a/tests/request_methods/test_feeds.py b/tests/request_methods/test_feeds.py index 78491717..c3354813 100644 --- a/tests/request_methods/test_feeds.py +++ b/tests/request_methods/test_feeds.py @@ -4,16 +4,7 @@ import unittest import datetime import mws -from .utils import CommonRequestTestTools - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - - -def transform_date(date): - return quote(date.isoformat(), safe='-_.~') +from .utils import CommonRequestTestTools, transform_date class FeedsTestCase(unittest.TestCase, CommonRequestTestTools): diff --git a/tests/request_methods/test_finances.py b/tests/request_methods/test_finances.py index eb87957c..d3c7acaf 100644 --- a/tests/request_methods/test_finances.py +++ b/tests/request_methods/test_finances.py @@ -4,16 +4,7 @@ import unittest import datetime import mws -from .utils import CommonRequestTestTools - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - - -def transform_date(date): - return quote(date.isoformat(), safe='-_.~') +from .utils import CommonRequestTestTools, transform_date class FinancesTestCase(unittest.TestCase, CommonRequestTestTools): diff --git a/tests/request_methods/test_inboundshipments.py b/tests/request_methods/test_inboundshipments.py index de367e54..8042468f 100644 --- a/tests/request_methods/test_inboundshipments.py +++ b/tests/request_methods/test_inboundshipments.py @@ -6,24 +6,8 @@ import mws from mws.apis.inbound_shipments import parse_item_args from mws.mws import MWSError -from .utils import CommonRequestTestTools - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - - -def transform_date(date): - return quote(date.isoformat(), safe='-_.~') - - -def transform_string(s): - return quote(s, safe='-_.~') - - -def transform_bool(b): - return str(b).lower() +from .utils import CommonRequestTestTools, transform_date, transform_bool +from .utils import transform_string class ParseItemArgsTestCase(unittest.TestCase): diff --git a/tests/request_methods/test_inventory.py b/tests/request_methods/test_inventory.py index b9c0ff29..83572c1f 100644 --- a/tests/request_methods/test_inventory.py +++ b/tests/request_methods/test_inventory.py @@ -4,16 +4,7 @@ import unittest import datetime import mws -from .utils import CommonRequestTestTools - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - - -def transform_date(date): - return quote(date.isoformat(), safe='-_.~') +from .utils import CommonRequestTestTools, transform_date class InventoryTestCase(unittest.TestCase, CommonRequestTestTools): diff --git a/tests/request_methods/test_orders.py b/tests/request_methods/test_orders.py index 4f9a8385..e3707f50 100644 --- a/tests/request_methods/test_orders.py +++ b/tests/request_methods/test_orders.py @@ -4,20 +4,7 @@ import datetime import unittest import mws -from .utils import CommonRequestTestTools - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - - -def transform_date(date): - return quote(date.isoformat(), safe='-_.~') - - -def transform_bool(b): - return str(b).lower() +from .utils import CommonRequestTestTools, transform_date class OrdersTestCase(unittest.TestCase, CommonRequestTestTools): diff --git a/tests/request_methods/test_products.py b/tests/request_methods/test_products.py index 9c533aa5..1d924adb 100644 --- a/tests/request_methods/test_products.py +++ b/tests/request_methods/test_products.py @@ -3,20 +3,7 @@ """ import unittest import mws -from .utils import CommonRequestTestTools - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - - -def transform_string(s): - return quote(s, safe='-_.~') - - -def transform_bool(b): - return str(b).lower() +from .utils import CommonRequestTestTools, transform_bool, transform_string class ProductsTestCase(unittest.TestCase, CommonRequestTestTools): diff --git a/tests/request_methods/test_recommendations.py b/tests/request_methods/test_recommendations.py index 620f9f20..cfbb6acd 100644 --- a/tests/request_methods/test_recommendations.py +++ b/tests/request_methods/test_recommendations.py @@ -3,16 +3,7 @@ """ import unittest import mws -from .utils import CommonRequestTestTools - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - - -def transform_string(s): - return quote(s, safe='-_.~') +from .utils import CommonRequestTestTools, transform_string class RecommendationsTestCase(unittest.TestCase, CommonRequestTestTools): diff --git a/tests/request_methods/test_reports.py b/tests/request_methods/test_reports.py index c03be2ab..490507cb 100644 --- a/tests/request_methods/test_reports.py +++ b/tests/request_methods/test_reports.py @@ -4,20 +4,7 @@ import datetime import unittest import mws -from .utils import CommonRequestTestTools - -try: - from urllib.parse import quote -except ImportError: - from urllib import quote - - -def transform_date(date): - return quote(date.isoformat(), safe='-_.~') - - -def transform_bool(b): - return str(b).lower() +from .utils import CommonRequestTestTools, transform_date, transform_bool class ReportsTestCase(unittest.TestCase, CommonRequestTestTools): diff --git a/tests/request_methods/utils.py b/tests/request_methods/utils.py index 16139db1..292b719e 100644 --- a/tests/request_methods/utils.py +++ b/tests/request_methods/utils.py @@ -3,6 +3,11 @@ """ import datetime +try: + from urllib.parse import quote +except ImportError: + from urllib import quote + class CommonRequestTestTools(object): CREDENTIAL_ACCESS = 'cred_access' @@ -32,3 +37,15 @@ def test_service_status(self): response = self.api.get_service_status() # Only key we care about here is GetServiceStatus self.assertEqual(response['Action'], 'GetServiceStatus') + + +def transform_string(s): + return quote(s, safe='-_.~') + + +def transform_bool(b): + return str(b).lower() + + +def transform_date(date): + return quote(date.isoformat(), safe='-_.~') From 27d6a05af675f572c5efecb35552deb80eeccafe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Sun, 6 May 2018 22:34:50 +0200 Subject: [PATCH 12/19] param test for wrong datatype exception --- tests/request_methods/test_reports.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/request_methods/test_reports.py b/tests/request_methods/test_reports.py index 490507cb..1c556548 100644 --- a/tests/request_methods/test_reports.py +++ b/tests/request_methods/test_reports.py @@ -48,6 +48,26 @@ def test_request_report(self): self.assertEqual(params['MarketplaceIdList.Id.1'], marketplace_ids[0]) self.assertEqual(params['MarketplaceIdList.Id.2'], marketplace_ids[1]) + def test_parameter_error(self): + """ + RequestReport wrong parameter + """ + # list will throw error + report_type = ['_GET_FLAT_FILE_OPEN_LISTINGS_DATA_'] + start_date = datetime.datetime(2018, 4, 30, 22, 59, 59) + end_date = datetime.datetime(2018, 4, 30, 23, 59, 59) + marketplace_ids = [ + 'iQzBCmf1y3', + 'wH9q0CiEMp', + ] + with self.assertRaises(mws.MWSError): + self.api.request_report( + report_type=report_type, + start_date=start_date, + end_date=end_date, + marketplace_ids=marketplace_ids, + ) + def test_get_report_request_list(self): """ GetReportRequestList operation. From 57cfc330b6c28be35189ef1666677a05b20a173e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Tue, 8 May 2018 21:27:33 +0200 Subject: [PATCH 13/19] clean all parameters at once see idea from GriceTurrble in this pull request --- mws/mws.py | 20 ++++++++------------ tests/request_methods/utils.py | 6 ++++-- tests/test_utils.py | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/mws/mws.py b/mws/mws.py index 3777e2e3..e0e3651d 100644 --- a/mws/mws.py +++ b/mws/mws.py @@ -75,20 +75,19 @@ def calc_request_description(params): "bar=4&baz=potato&foo=1" """ description_items = [] - params = clean_extra_data(params) for item in sorted(params.keys()): encoded_val = params[item] description_items.append('{}={}'.format(item, encoded_val)) return '&'.join(description_items) -def clean_extra_data(extra_data): +def clean_params(params): """Input cleanup and prevent a lot of common input mistakes.""" # silently remove parameter where values are empty - extra_data = {k: v for k, v in extra_data.items() if v} + params = {k: v for k, v in params.items() if v} - extra_data_enc = dict() - for key, value in extra_data.items(): + params_enc = dict() + for key, value in params.items(): if isinstance(value, (dict, list, set, tuple)): message = 'expected string or datetime datatype, got {},'\ 'for key {} and value {}'.format( @@ -100,8 +99,8 @@ def clean_extra_data(extra_data): value = str(value).lower() value = str(value) - extra_data_enc[key] = quote(value, safe='-_.~') - return extra_data_enc + params_enc[key] = quote(value, safe='-_.~') + return params_enc def remove_namespace(xml): @@ -264,14 +263,11 @@ def make_request(self, extra_data, method="GET", **kwargs): """ Make request to Amazon MWS API with these parameters """ - # Remove all keys with an empty value because - # Amazon's MWS does not allow such a thing. - - extra_data = clean_extra_data(extra_data) - params = self.get_default_params() proxies = self.get_proxies() params.update(extra_data) + params = clean_params(params) + if self._test_request_params: # Testing method: return the params from this request before the request is made. return params diff --git a/tests/request_methods/utils.py b/tests/request_methods/utils.py index 292b719e..74e45583 100644 --- a/tests/request_methods/utils.py +++ b/tests/request_methods/utils.py @@ -27,11 +27,13 @@ def assert_common_params(self, params): # If test fails here, check that method. self.assertEqual(params['SignatureMethod'], 'HmacSHA256') self.assertEqual(params['SignatureVersion'], '2') - isoformat_str = "%Y-%m-%dT%H:%M:%S" + isoformat_str = "%Y-%m-%dT%H%%3A%M%%3A%S" try: datetime.datetime.strptime(params['Timestamp'], isoformat_str) except ValueError: - self.fail("Timestamp expected an ISO-8601 datetime string with format [YYYY-MM-DDTHH:MM:SS].") + self.fail( + "Timestamp expected an ISO-8601 datetime string url encoded" + " with format [YYYY-MM-DDTHH%3AMM%3ASS].") def test_service_status(self): response = self.api.get_service_status() diff --git a/tests/test_utils.py b/tests/test_utils.py index 6b716da3..0f181dc3 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -11,7 +11,7 @@ def test_calc_request_description(access_key, account_id): 'AWSAccessKeyId': access_key, 'Markets': account_id, 'SignatureVersion': '2', - 'Timestamp': '2017-08-12T19:40:35Z', + 'Timestamp': '2017-08-12T19%3A40%3A35Z', 'Version': '2017-01-01', 'SignatureMethod': 'HmacSHA256', }) From b1583dfbaad499242ab732e4b7121ec6fabb0a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Benk=C3=B6?= Date: Fri, 11 May 2018 14:28:37 +0200 Subject: [PATCH 14/19] remove dt_iso_or_none no need for this --- mws/apis/inbound_shipments.py | 6 ------ mws/utils.py | 17 +---------------- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/mws/apis/inbound_shipments.py b/mws/apis/inbound_shipments.py index 1792cc2e..b4b395cf 100644 --- a/mws/apis/inbound_shipments.py +++ b/mws/apis/inbound_shipments.py @@ -570,9 +570,6 @@ def list_inbound_shipments(self, shipment_ids=None, shipment_statuses=None, Docs: http://docs.developer.amazonservices.com/en_US/fba_inbound/FBAInbound_ListInboundShipments.html """ - last_updated_after = utils.dt_iso_or_none(last_updated_after) - last_updated_before = utils.dt_iso_or_none(last_updated_before) - data = { 'Action': 'ListInboundShipments', 'LastUpdatedAfter': last_updated_after, @@ -605,9 +602,6 @@ def list_inbound_shipment_items(self, shipment_id=None, last_updated_after=None, Docs: http://docs.developer.amazonservices.com/en_US/fba_inbound/FBAInbound_ListInboundShipmentItems.html """ - last_updated_after = utils.dt_iso_or_none(last_updated_after) - last_updated_before = utils.dt_iso_or_none(last_updated_before) - data = { 'Action': 'ListInboundShipmentItems', 'ShipmentId': shipment_id, diff --git a/mws/utils.py b/mws/utils.py index 25a71e8a..57872627 100644 --- a/mws/utils.py +++ b/mws/utils.py @@ -27,6 +27,7 @@ class ObjectDict(dict): >>> a.water 'water' """ + def __init__(self, initd=None): if initd is None: initd = {} @@ -271,22 +272,6 @@ def unique_list_order_preserved(seq): return [x for x in seq if not (x in seen or seen_add(x))] -def dt_iso_or_none(dt_obj): - """ - If dt_obj is a datetime, return isoformat() - TODO: if dt_obj is a string in iso8601 already, return it back - Otherwise, return None - """ - # If d is a datetime object, format it to iso and return - if isinstance(dt_obj, datetime.datetime): - return dt_obj.isoformat() - - # TODO: if dt_obj is a string in iso8601 already, return it - - # none of the above: return None - return None - - def get_utc_timestamp(): """ Returns the current UTC timestamp in ISO-8601 format. From ba0f363238768e90048a6271b3dd2aa695ac2a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Zafra=20G=C3=B3mez?= Date: Fri, 4 May 2018 18:03:12 +0200 Subject: [PATCH 15/19] Feeds example. Use of ".parsed" changed. (#66) * Feeds example. * Feeds example. Use of ".parsed" changed. From b1b206658451a6f4ea5ee27d627d6df308439bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Zafra=20G=C3=B3mez?= Date: Fri, 4 May 2018 18:03:12 +0200 Subject: [PATCH 16/19] Revert "Feeds example. Use of ".parsed" changed. (#66)" This reverts commit ba0f363238768e90048a6271b3dd2aa695ac2a0e. From 9526f2d999ef9b5c47a56050b93eb029a6075191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Zafra=20G=C3=B3mez?= Date: Fri, 4 May 2018 18:03:12 +0200 Subject: [PATCH 17/19] Revert "Feeds example. Use of ".parsed" changed. (#66)" This reverts commit e87012bebaebce194377683ae65ceaa25330d213. --- docs/source/feeds.rst | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/source/feeds.rst b/docs/source/feeds.rst index ec5fdc88..31f3cd70 100644 --- a/docs/source/feeds.rst +++ b/docs/source/feeds.rst @@ -13,11 +13,11 @@ To build your own XML data you should use Amazon documentation about feed types access_key = 'accesskey' #replace with your access key seller_id = 'merchantid' #replace with your seller id secret_key = 'secretkey' #replace with your secret key - MWS_MARKETPLACE_ID = 'ATVPDKIKX0DER' + marketplace_usa = 'ATVPDKIKX0DER' feed = mws.Feeds(access_key, secret_key, seller_id, region='US') - print("### Product feed ###") + print "### Product feed ###" xml = """
@@ -54,11 +54,10 @@ To build your own XML data you should use Amazon documentation about feed types """ - response = feed.submit_feed(xml, "_POST_PRODUCT_DATA_", MWS_MARKETPLACE_ID) - print(response.parsed) + response = feed.submit_feed(xml, "_POST_PRODUCT_DATA_", MSW_MARKETPLACE_ID).parsed + print response - - print("### Inventory feed ###") + print "### Inventory feed ###" xml = """
@@ -75,11 +74,11 @@ To build your own XML data you should use Amazon documentation about feed types """ - response = feed.submit_feed(xml, "_POST_INVENTORY_AVAILABILITY_DATA_", MWS_MARKETPLACE_ID) - print(response.parsed) + response = feed.submit_feed(xml, "_POST_INVENTORY_AVAILABILITY_DATA_", MSW_MARKETPLACE_ID).parsed + print response - print("### Product image feed ###") + print "### Product image feed ###" xml = """
@@ -97,5 +96,5 @@ To build your own XML data you should use Amazon documentation about feed types """ - response = feed.submit_feed(xml, "_POST_PRODUCT_IMAGE_DATA_", MWS_MARKETPLACE_ID) - print(response.parsed) + response = feed.submit_feed(xml, "_POST_PRODUCT_IMAGE_DATA_", MSW_MARKETPLACE_ID).parsed + print response \ No newline at end of file From b97144b220dcd639b92807d2a070296130972ca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Zafra=20G=C3=B3mez?= Date: Fri, 4 May 2018 18:03:12 +0200 Subject: [PATCH 18/19] Revert "Feeds example. Use of ".parsed" changed. (#66)" This reverts commit 77d3ea7ee3e0b387e26a0137c70c8a0a288d7f2c. From bbe487842c3c1111131122dd27566f22cd42e2ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Zafra=20G=C3=B3mez?= Date: Thu, 3 May 2018 13:31:47 +0200 Subject: [PATCH 19/19] Revert "Feeds example. (#64)" This reverts commit 2a1858371c5e3dddfe05a0581ba13aae9e58b144. --- docs/source/feeds.rst | 97 ------------------------------------------- 1 file changed, 97 deletions(-) diff --git a/docs/source/feeds.rst b/docs/source/feeds.rst index 31f3cd70..8a354d25 100644 --- a/docs/source/feeds.rst +++ b/docs/source/feeds.rst @@ -1,100 +1,3 @@ ############ Feeds ############ - -There are several types of feeds and some of them are used to send product data. Here is a example of how to send product basic data, inventory data and product images. - -To build your own XML data you should use Amazon documentation about feed types that you can find here: http://docs.developer.amazonservices.com/en_US/feeds/Feeds_FeedType.html#FeedType_Enumeration__ProductInventoryFeeds. Also Python xml.etree.ElementTree module can be very useful. - -.. code-block:: Python - - import mws - - access_key = 'accesskey' #replace with your access key - seller_id = 'merchantid' #replace with your seller id - secret_key = 'secretkey' #replace with your secret key - marketplace_usa = 'ATVPDKIKX0DER' - - feed = mws.Feeds(access_key, secret_key, seller_id, region='US') - - print "### Product feed ###" - xml = """ - -
- 1.01 - merchantid -
- Product - - 1 - Update - - 153024 - - EAN - 8427426004696 - - - DENTAID Interprox Micro 18 units - Dentaid - Interprox Plus Micro is designed to remove oral biofilm (bacterial plaque) build-up from 0.9 mm* interproximal spaces, particularly in the premolar and molar areas. - 15.76 - Dentaid - 8427426004696 - - - - - - English - - - - - - -
""" - response = feed.submit_feed(xml, "_POST_PRODUCT_DATA_", MSW_MARKETPLACE_ID).parsed - print response - - print "### Inventory feed ###" - xml = """ - -
- 1.01 - merchantid -
- Inventory - - 1 - Update - - 153024 - 2 - - -
""" - response = feed.submit_feed(xml, "_POST_INVENTORY_AVAILABILITY_DATA_", MSW_MARKETPLACE_ID).parsed - print response - - - print "### Product image feed ###" - xml = """ - -
- 1.01 - merchantid -
- ProductImage - - 1 - Update - - 235609 - Main - http://your-domain.org/235609.JPG - - -
""" - response = feed.submit_feed(xml, "_POST_PRODUCT_IMAGE_DATA_", MSW_MARKETPLACE_ID).parsed - print response \ No newline at end of file