示例#1
0
    def get_competitive_pricing(self,
                                marketplace_id,
                                id_type,
                                id_list,
                                debug=None):
        """
		Requests the competitive pricing for the specified marketplace
		products.

		*marketplace_id* (``str``) is the ID of the Amazon Marketplace the
		products belong to.

		*id_type* (``str``) is the type of ID used. This can only be
		"ASIN" or "SellerSKU".

		*id_list* (**sequence**) contains the ID (``str``) of each product
		to get. A maximum of 20 IDs can be requested at a single time.

		Returns the response XML (``str``).
		"""
        if not isinstance(marketplace_id, six.string_types):
            raise TypeError(
                "marketplace_id:{!r} is not a str.".format(marketplace_id))
        elif not marketplace_id:
            raise ValueError(
                "marketplace_id:{!r} cannot be empty.".format(marketplace_id))

        if not isinstance(id_type, six.string_types):
            raise TypeError("id_type:{!r} is not a str.".format(id_type))
        elif not id_type:
            raise ValueError("id_type:{!r} cannot be empty.".format(id_type))

        if not is_sequence(id_list):
            raise TypeError("id_list:{!r} is not a sequence.".format(id_list))
        elif not id_list:
            raise ValueError("id_list:{!r} cannot be empty.".format(id_list))
        elif len(id_list) > 20:
            raise ValueError(
                "id_list length:{} cannot be greater than 20.".format(
                    len(id_list)))

        args = self.new_args()
        args['IdType'] = id_type
        if id_type == 'ASIN':
            args['Action'] = ACTIONS['get_competitive_pricing_for_asin']
            args.update({
                'ASINList.ASIN.{}'.format(i): asin
                for i, asin in enumerate(id_list, 1)
            })
        elif id_type == 'SellerSKU':
            args['Actions'] = ACTIONS['get_competitive_pricing_for_sku']
            args.update({
                'SellerSKUList.SellerSKU.{}'.format(i): sku
                for i, sku in enumerate(id_list, 1)
            })
        else:
            raise ValueError(
                "id_type:{!r} is not 'ASIN' or 'SellerSKU'.".format(id_type))

        return self.send_request(args, path=self.path, debug=debug)
示例#2
0
def submission_args(submissions, name=None):
    """
	Converts the specified Feed Submission IDs into their resepctive URL
	query arguments.

	*submissions* (**sequence**) contains each Feed Submission ID
	(``str``).

	*name* (``str``) is the name to use when an error occurs.

	Returns a ``list`` containing each *key*-*submission_id* ``tuple``.

		- *key* (``str``) is the query argument key for *submission_id*.

		- *submission_id* (``str``) is the Feed Submission ID.
	"""
    if not name:
        name = 'submissions'

    if not is_sequence(submissions):
        raise TypeError("{}:{!r} is not a sequence.".format(name, submissions))

    args = []
    for i, sub_id in enumerate(submissions):
        if not isinstance(sub_id, six.string_types):
            raise TypeError("{}[{}]:{!r} is not a string.".format(
                name, i, sub_id))
        elif not sub_id:
            raise ValueError("{}[{}]:{!r} cannot be empty.".format(
                name, i, sub_id))
        sub_id = encode_string(sub_id, 'ASCII', name="{}[{}]".format(name, i))

        args.append(('FeedSubmissionIdList.Id.{}'.format(i + 1), sub_id))

    return args
示例#3
0
def request_args(requests, name=None):
	"""
	Converts the specified Report Request IDs into their respective URL
	query arguments.
	
	*requests* (**sequence**) contains each Report Request ID (``str``).
		
	*name* (``str``) is the name to use when an error occurs.
	
	Returns a ``list`` containing each *key*-*request_id* ``tuple``.
	
		- *key* (``str``) is the query argument key for *request_id*.
		
		- *request_id* (``str``) is the Report Request ID.
	"""
	if not name:
		name = 'requests'

	if not is_sequence(requests):
		raise TypeError("{}:{!r} is not a sequence.".format(name, requests))
		
	args = []
	for i, request_id in enumerate(requests, 0):
		if not isinstance(request_id, basestring):
			raise TypeError("{}[{}]:{!r} is not a string.".format(name, i, request_id))
		elif not request_id:
			raise ValueError("{}[{}]:{!r} cannot be empty.".format(name, i, request_id))
		request_id = encode_string(request_id, 'ASCII', name="{}[{}]".format(name, i))
		
		args.append(('ReportRequestIdList.Id.{}'.format(i + 1), request_id))

	return args
示例#4
0
def feed_type_args(feed_types, name=None):
	"""
	Converts the specified Feed Types into their resepctive URL query
	arguments.

	*feed_types* (**sequence**) contains each Feed Type (``str``). This
	can contain any of the keys or values from ``FEED_TYPES``.

	*name* (``str``) is the name to use when an error occurs.

	Returns a ``list`` containing each *key*-*feed_type* ``tuple``.

		- *key* (``str``) is the query argument key for *feed_type*.

		- *feed_type* (``str``) is the Feed Type ID.
	"""
	if not name:
		name = 'feed_types'

	if not is_sequence(feed_types):
		raise TypeError("{}:{!r} is not a sequence.".format(name, feed_types))

	args = []
	for i, feed_type in enumerate(feed_types):
		feed_type = FEED_TYPES.get(feed_type, feed_type)
		if not isinstance(feed_type, str):
			raise TypeError("{}[{}]:{!r} is not a str.".format(name, i, feed_type))
		elif not feed_type:
			raise ValueError("{}[{}]:{!r} cannot be empty.".format(name, i, feed_type))
		feed_type = encode_string(feed_type, 'ASCII', name="{}[{}]".format(name, i))

		args.append(('FeedTypeList.Type.{}'.format(i + 1), feed_type))

	return args
示例#5
0
def report_type_args(report_types, name=None):
	"""
	Converts the specified Report Types into their respective URL query
	arguments.
	
	*report_types* (**sequence**) contains each Report Type (``str``).
	This can contain any keys or values from ``REPORT_TYPES``.
	
	*name* (``str``) is the name to use when an error occurs.
	
	Returns a ``list`` containing each *key*-*report_type* ``tuple``.
	
		- *key* (``str``) is the query argument key for *report_type*.
		
		- *report_type* (``str``) is the Report Type.
	"""
	if not name:
		name = 'report_types'

	if not is_sequence(report_types):
		raise TypeError("{}:{!r} is not a sequence.".format(name, report_types))
		
	args = []
	for i, report_type in enumerate(report_types, 0):
		report_type = REPORT_TYPES.get(report_type, report_type)
		if not isinstance(report_type, basestring):
			raise TypeError("{}[{}]:{!r} is not a string.".format(name, i, report_type))
		elif not report_type:
			raise ValueError("{}[{}]:{!r} cannot be empty.".format(name, i, report_type))
		report_type = encode_string(report_type, 'ASCII', name="{}[{}]".format(name, i))
		
		args.append(('ReportTypeList.Type.{}'.format(i + 1), report_type))

	return args
示例#6
0
	def update_report_acknowledgements(self, reports, marketplaces=None, debug=None):
		"""
		Updates the acknowledged status of the specified Reports.
		
		*reports* (**sequence**) is the list of Report IDs (``int``) to
		update. The maximum number of Reports that can be specified is 100.
		
		*marketplaces* (**sequence**) is the list of Amazon Marketplace IDs
		(``str``). Default is ``None`` for all marketplaces.
		"""
		if not is_sequence(reports):
			raise TypeError("reports:{!r} is not a sequence.".format(reports))
		elif len(reports) < 0 or 100 < len(reports):
			raise ValueError("reports len:{!r} must be between 1 and 100 inclusive.".format(len(reports)))
		
		# Build args.
		args = self.new_args()
		args['Action'] = 'UpdateReportAcknowledgements'
		args['Acknowledged'] = 'true'
			
		for i, report_id in enumerate(reports, 0):
			if not isinstance(report_id, basestring):
				raise TypeError("reports[{}]:{!r} is not a string.".format(i, report_id))
			elif not report_id:
				raise ValueError("reports[{}]:{!r} cannot be empty.".format(i, report_id))
			report_id = encode_string(report_id, 'ASCII', name="reports[{}]".format(i))
			
			args['ReportIdList.Id.{}'.format(report_id)] = report_id
			
		if marketplaces is not None:
			args.update(marketplace_args(marketplaces, name='marketplaces'))
		
		# Send Request.
		return self.send_request(args, debug=debug)
示例#7
0
def status_args(statuses, name=None):
	"""
	Converts the specified Feed Processing Statuses into their respective
	URL query arguments.

	*statuses* (**sequence**) contains each Feed Processing Status
	(``str``). This can contain any of the keys or value from ``PROCESSING_STATUSES``.

	*name* (``str``) is the name to use when an error occurs.

	Returns a ``list`` containing each *key*-*status* ``tuple``.

		- *key* (``str``) is the query argument key for *status*.

		- *status* (``str``) is the Feed Processing Status.
	"""
	if not name:
		name = 'statuses'

	if not is_sequence(statuses):
		raise TypeError("{}:{!r} is not a sequence.".format(name, statuses))

	args = []
	for i, status in enumerate(statuses):
		status = PROCESSING_STATUSES.get(status, status)
		if not isinstance(status, str):
			raise TypeError("{}[{}]:{!r} is not a str.".format(name, i, status))
		elif not status:
			raise ValueError("{}[{}]:{!r} cannot be empty.".format(name, i, status))
		status = encode_string(status, 'ASCII', name="{}[{}]".format(name, i))

		args.append(('FeedProcessingStatusList.Status.{}'.format(i + 1), status))

	return args
示例#8
0
def submission_args(submissions, name=None):
	"""
	Converts the specified Feed Submission IDs into their resepctive URL
	query arguments.

	*submissions* (**sequence**) contains each Feed Submission ID
	(``str``).

	*name* (``str``) is the name to use when an error occurs.

	Returns a ``list`` containing each *key*-*submission_id* ``tuple``.

		- *key* (``str``) is the query argument key for *submission_id*.

		- *submission_id* (``str``) is the Feed Submission ID.
	"""
	if not name:
		name = 'submissions'

	if not is_sequence(submissions):
		raise TypeError("{}:{!r} is not a sequence.".format(name, submissions))

	args = []
	for i, sub_id in enumerate(submissions):
		if not isinstance(sub_id, basestring):
			raise TypeError("{}[{}]:{!r} is not a string.".format(name, i, sub_id))
		elif not sub_id:
			raise ValueError("{}[{}]:{!r} cannot be empty.".format(name, i, sub_id))
		sub_id = encode_string(sub_id, 'ASCII', name="{}[{}]".format(name, i))

		args.append(('FeedSubmissionIdList.Id.{}'.format(i + 1), sub_id))

	return args
示例#9
0
	def get_my_price(self, marketplace_id, id_type, id_list, condition=None, verbose=None):
		"""
		Requests the seller's price for the specified marketplace products.

		*marketplace_id* (``str``) is the ID of the Amazon Marketplace the
		products belong to.

		*id_type* (``str``) is the type of ID used. This can only be
		"ASIN" or "SellerSKU".

		*id_list* (**sequence**) contains the ID (``str``) of each product
		to get. A maximum of 20 IDs can be requested at a single time.

		*condition* (``str``) optionally filters the returned listings to be
		based upon item condition. This can be any key or value from
		``ITEM_CONDITIONS``. Default is ``None`` for no filter.

		Returns the response XML (``str``).
		"""
		if not isinstance(marketplace_id, str):
			raise TypeError("marketplace_id:{!r} is not a str.".format(marketplace_id))
		elif not marketplace_id:
			raise ValueError("marketplace_id:{!r} cannot be empty.".format(marketplace_id))

		if not isinstance(id_type, str):
			raise TypeError("id_type:{!r} is not a str.".format(id_type))
		elif not id_type:
			raise ValueError("id_type:{!r} cannot be empty.".format(id_type))

		if not is_sequence(id_list):
			raise TypeError("id_list:{!r} is not a sequence.".format(id_list))
		elif not id_list:
			raise ValueError("id_list:{!r} cannot be empty.".format(id_list))
		elif len(id_list) > 20:
			raise ValueError("id_list length:{} cannot be greater than 20.".format(len(id_list)))

		if condition is not None:
			condition = ITEM_CONDITIONS.get(condition, condition)
			if not isinstance(condition, str):
				raise TypeError("condition:{!r} is not a str.".format(condition))
			elif not condition:
				raise ValueError("condition:{!r} cannot be empty.".format(condition))

		args = self.new_args()
		args['IdType'] = id_type
		if id_type == 'ASIN':
			args['Action'] = ACTIONS['get_my_price_for_asin']
			args.update({'ASINList.ASIN.{}'.format(i): asin for i, asin in enumerate(id_list, 1)})
		elif id_type == 'SellerSKU':
			args['Actions'] = ACTIONS['get_my_price_for_sku']
			args.update({'SellerSKUList.SellerSKU.{}'.format(i): sku for i, sku in enumerate(id_list, 1)})
		else:
			raise ValueError("id_type:{!r} is not 'ASIN' or 'SellerSKU'.".format(id_type))
		if condition is not None:
			args['ItemCondition'] = condition

		return self.send_request(args, path=self.path, verbose=verbose)
示例#10
0
	def get_my_price(self, marketplace_id, id_type, id_list, condition=None, verbose=None):
		"""
		Requests the seller's price for the specified marketplace products.

		*marketplace_id* (``str``) is the ID of the Amazon Marketplace the
		products belong to.

		*id_type* (``str``) is the type of ID used. This can only be
		"ASIN" or "SellerSKU".

		*id_list* (**sequence**) contains the ID (``str``) of each product
		to get. A maximum of 20 IDs can be requested at a single time.

		*condition* (``str``) optionally filters the returned listings to be
		based upon item condition. This can be any key or value from
		``ITEM_CONDITIONS``. Default is ``None`` for no filter.

		Returns the response XML (``str``).
		"""
		if not isinstance(marketplace_id, six.string_types):
			raise TypeError("marketplace_id:{!r} is not a str.".format(marketplace_id))
		elif not marketplace_id:
			raise ValueError("marketplace_id:{!r} cannot be empty.".format(marketplace_id))

		if not isinstance(id_type, six.string_types):
			raise TypeError("id_type:{!r} is not a str.".format(id_type))
		elif not id_type:
			raise ValueError("id_type:{!r} cannot be empty.".format(id_type))

		if not is_sequence(id_list):
			raise TypeError("id_list:{!r} is not a sequence.".format(id_list))
		elif not id_list:
			raise ValueError("id_list:{!r} cannot be empty.".format(id_list))
		elif len(id_list) > 20:
			raise ValueError("id_list length:{} cannot be greater than 20.".format(len(id_list)))

		if condition is not None:
			condition = ITEM_CONDITIONS.get(condition, condition)
			if not isinstance(condition, six.string_types):
				raise TypeError("condition:{!r} is not a str.".format(condition))
			elif not condition:
				raise ValueError("condition:{!r} cannot be empty.".format(condition))

		args = self.new_args()
		args['IdType'] = id_type
		if id_type == 'ASIN':
			args['Action'] = ACTIONS['get_my_price_for_asin']
			args.update({'ASINList.ASIN.{}'.format(i): asin for i, asin in enumerate(id_list, 1)})
		elif id_type == 'SellerSKU':
			args['Actions'] = ACTIONS['get_my_price_for_sku']
			args.update({'SellerSKUList.SellerSKU.{}'.format(i): sku for i, sku in enumerate(id_list, 1)})
		else:
			raise ValueError("id_type:{!r} is not 'ASIN' or 'SellerSKU'.".format(id_type))
		if condition is not None:
			args['ItemCondition'] = condition

		return self.send_request(args, path=self.path, verbose=verbose)
示例#11
0
    def update_report_acknowledgements(self,
                                       reports,
                                       acknowledged=None,
                                       marketplaces=None,
                                       debug=None):
        """
		Updates the acknowledged status of the specified Reports.

		*reports* (**sequence**) is the list of Report IDs (``int``) to
		update. The maximum number of Reports that can be specified is 100.

		*acknowledged* (**boolean**) is whether or not to mark the reports
		passed as acknowledged. Default is ``None``. Amazon MWS treats the
		absense of acknowledged by defaulting the value to True.

		*marketplaces* (**sequence**) is the list of Amazon Marketplace IDs
		(``str``). Default is ``None`` for all marketplaces.
		"""
        if not is_sequence(reports):
            raise TypeError("reports:{!r} is not a sequence.".format(reports))
        elif len(reports) < 0 or 100 < len(reports):
            raise ValueError(
                "reports len:{!r} must be between 1 and 100 inclusive.".format(
                    len(reports)))

        # Build args.
        args = self.new_args()
        args['Action'] = 'UpdateReportAcknowledgements'

        if acknowledged is True:
            args['Acknowledged'] = 'true'
        elif acknowledged is False:
            args['Acknowledged'] = 'false'
        elif acknowledged is not None:
            raise TypeError(
                "reports['acknowledged']:{!r} is not boolean.".format(
                    acknowledged))

        for i, report_id in enumerate(reports, 1):
            if not isinstance(report_id, basestring):
                raise TypeError("reports[{}]:{!r} is not a string.".format(
                    i, report_id))
            elif not report_id:
                raise ValueError("reports[{}]:{!r} cannot be empty.".format(
                    i, report_id))
            report_id = encode_string(report_id,
                                      'ASCII',
                                      name="reports[{}]".format(i))

            args['ReportIdList.Id.{}'.format(i)] = report_id

        if marketplaces is not None:
            args.update(marketplace_args(marketplaces, name='marketplaces'))

        # Send Request.
        return self.send_request(args, debug=debug)
示例#12
0
    def get_products(self, marketplace_id, id_type, id_list, debug=None):
        """
		Requests the information for the specified marketplace products.

		*marketplace_id* (``str``) is the ID of the Amazon Marketplace the
		products are coming from.

		*id_type* (``str``) is the type of ID used. This can be only of the
		types listed under ``ID_TYPES``.

		*id_list* (**sequence**) contains the ID (``str``) of each product
		to get. A maximum of 10 ASINs, or 5 IDs of another type can be
		requested at a single time.

		Returns the response XML (``str``).
		"""
        if not isinstance(marketplace_id, six.string_types):
            raise TypeError(
                "marketplace_id:{!r} is not a str.".format(marketplace_id))
        elif not marketplace_id:
            raise ValueError(
                "marketplace_id:{!r} cannot be empty.".format(marketplace_id))

        if not isinstance(id_type, six.string_types):
            raise TypeError("id_type:{!r} is not a str.".format(id_type))
        elif not id_type:
            raise ValueError("id_type:{!r} cannot be empty.".format(id_type))

        if not is_sequence(id_list):
            raise TypeError("id_list:{!r} is not a sequence.".format(id_list))
        elif not id_list:
            raise ValueError("id_list:{!r} cannot be empty.".format(id_list))

        if len(id_list) > 5:
            raise ValueError(
                "id_list length:{} cannot be greater than 5.".format(
                    len(id_list)))

        args = self.new_args()
        if id_type == 'ASIN':
            args['Action'] = ACTIONS['get_products']
            args.update({
                'ASINList.ASIN.{}'.format(i): asin
                for i, asin in enumerate(id_list, 1)
            })
        else:
            args['IdType'] = id_type
            args['Action'] = ACTIONS['get_products_for_id']
            args.update({
                'IDList.ID.{}'.format(i): id_
                for i, id_ in enumerate(id_list, 1)
            })

        return self.send_request(args, path=self.path, debug=debug)
示例#13
0
	def get_competitive_pricing(self, marketplace_id, id_type, id_list, verbose=None):
		"""
		Requests the competitive pricing for the specified marketplace
		products.

		*marketplace_id* (``str``) is the ID of the Amazon Marketplace the
		products belong to.

		*id_type* (``str``) is the type of ID used. This can only be
		"ASIN" or "SellerSKU".

		*id_list* (**sequence**) contains the ID (``str``) of each product
		to get. A maximum of 20 IDs can be requested at a single time.

		Returns the response XML (``str``).
		"""
		if not isinstance(marketplace_id, six.string_types):
			raise TypeError("marketplace_id:{!r} is not a str.".format(marketplace_id))
		elif not marketplace_id:
			raise ValueError("marketplace_id:{!r} cannot be empty.".format(marketplace_id))

		if not isinstance(id_type, six.string_types):
			raise TypeError("id_type:{!r} is not a str.".format(id_type))
		elif not id_type:
			raise ValueError("id_type:{!r} cannot be empty.".format(id_type))

		if not is_sequence(id_list):
			raise TypeError("id_list:{!r} is not a sequence.".format(id_list))
		elif not id_list:
			raise ValueError("id_list:{!r} cannot be empty.".format(id_list))
		elif len(id_list) > 20:
			raise ValueError("id_list length:{} cannot be greater than 20.".format(len(id_list)))

		args = self.new_args()
		args['IdType'] = id_type
		if id_type == 'ASIN':
			args['Action'] = ACTIONS['get_competitive_pricing_for_asin']
			args.update({'ASINList.ASIN.{}'.format(i): asin for i, asin in enumerate(id_list, 1)})
		elif id_type == 'SellerSKU':
			args['Actions'] = ACTIONS['get_competitive_pricing_for_sku']
			args.update({'SellerSKUList.SellerSKU.{}'.format(i): sku for i, sku in enumerate(id_list, 1)})
		else:
			raise ValueError("id_type:{!r} is not 'ASIN' or 'SellerSKU'.".format(id_type))

		return self.send_request(args, path=self.path, verbose=verbose)
示例#14
0
	def update_report_acknowledgements(self, reports, acknowledged=None, marketplaces=None, debug=None):
		"""
		Updates the acknowledged status of the specified Reports.

		*reports* (**sequence**) is the list of Report IDs (``int``) to
		update. The maximum number of Reports that can be specified is 100.

		*acknowledged* (**boolean**) is whether or not to mark the reports
		passed as acknowledged. Default is ``None``. Amazon MWS treats the
		absense of acknowledged by defaulting the value to True.

		*marketplaces* (**sequence**) is the list of Amazon Marketplace IDs
		(``str``). Default is ``None`` for all marketplaces.
		"""
		if not is_sequence(reports):
			raise TypeError("reports:{!r} is not a sequence.".format(reports))
		elif len(reports) < 0 or 100 < len(reports):
			raise ValueError("reports len:{!r} must be between 1 and 100 inclusive.".format(len(reports)))

		# Build args.
		args = self.new_args()
		args['Action'] = 'UpdateReportAcknowledgements'

		if acknowledged is True:
			args['Acknowledged'] = 'true'
		elif acknowledged is False:
			args['Acknowledged'] = 'false'
		elif acknowledged is not None:
			raise TypeError("reports['acknowledged']:{!r} is not boolean.".format(acknowledged))

		for i, report_id in enumerate(reports, 1):
			if not isinstance(report_id, six.string_types):
				raise TypeError("reports[{}]:{!r} is not a string.".format(i, report_id))
			elif not report_id:
				raise ValueError("reports[{}]:{!r} cannot be empty.".format(i, report_id))
			report_id = encode_string(report_id, 'ASCII', name="reports[{}]".format(i))

			args['ReportIdList.Id.{}'.format(i)] = report_id

		if marketplaces is not None:
			args.update(marketplace_args(marketplaces, name='marketplaces'))

		# Send Request.
		return self.send_request(args, debug=debug)
示例#15
0
	def get_products(self, marketplace_id, id_type, id_list, debug=None):
		"""
		Requests the information for the specified marketplace products.

		*marketplace_id* (``str``) is the ID of the Amazon Marketplace the
		products are coming from.

		*id_type* (``str``) is the type of ID used. This can be only of the
		types listed under ``ID_TYPES``.

		*id_list* (**sequence**) contains the ID (``str``) of each product
		to get. A maximum of 10 ASINs, or 5 IDs of another type can be
		requested at a single time.

		Returns the response XML (``str``).
		"""
		if not isinstance(marketplace_id, six.string_types):
			raise TypeError("marketplace_id:{!r} is not a str.".format(marketplace_id))
		elif not marketplace_id:
			raise ValueError("marketplace_id:{!r} cannot be empty.".format(marketplace_id))

		if not isinstance(id_type, six.string_types):
			raise TypeError("id_type:{!r} is not a str.".format(id_type))
		elif not id_type:
			raise ValueError("id_type:{!r} cannot be empty.".format(id_type))

		if not is_sequence(id_list):
			raise TypeError("id_list:{!r} is not a sequence.".format(id_list))
		elif not id_list:
			raise ValueError("id_list:{!r} cannot be empty.".format(id_list))

		if len(id_list) > 5:
			raise ValueError("id_list length:{} cannot be greater than 5.".format(len(id_list)))

		args = self.new_args()
		if id_type == 'ASIN':
			args['Action'] = ACTIONS['get_products']
			args.update({'ASINList.ASIN.{}'.format(i): asin for i, asin in enumerate(id_list, 1)})
		else:
			args['IdType'] = id_type
			args['Action'] = ACTIONS['get_products_for_id']
			args.update({'IDList.ID.{}'.format(i): id_ for i, id_ in enumerate(id_list, 1)})

		return self.send_request(args, path=self.path, debug=debug)
示例#16
0
def report_type_args(report_types, name=None):
    """
	Converts the specified Report Types into their respective URL query
	arguments.
	
	*report_types* (**sequence**) contains each Report Type (``str``).
	This can contain any keys or values from ``REPORT_TYPES``.
	
	*name* (``str``) is the name to use when an error occurs.
	
	Returns a ``list`` containing each *key*-*report_type* ``tuple``.
	
		- *key* (``str``) is the query argument key for *report_type*.
		
		- *report_type* (``str``) is the Report Type.
	"""
    if not name:
        name = 'report_types'

    if not is_sequence(report_types):
        raise TypeError("{}:{!r} is not a sequence.".format(
            name, report_types))

    args = []
    for i, report_type in enumerate(report_types, 0):
        report_type = REPORT_TYPES.get(report_type, report_type)
        if not isinstance(report_type, basestring):
            raise TypeError("{}[{}]:{!r} is not a string.".format(
                name, i, report_type))
        elif not report_type:
            raise ValueError("{}[{}]:{!r} cannot be empty.".format(
                name, i, report_type))
        report_type = encode_string(report_type,
                                    'ASCII',
                                    name="{}[{}]".format(name, i))

        args.append(('ReportTypeList.Type.{}'.format(i + 1), report_type))

    return args
示例#17
0
def feed_type_args(feed_types, name=None):
    """
	Converts the specified Feed Types into their resepctive URL query
	arguments.

	*feed_types* (**sequence**) contains each Feed Type (``str``). This
	can contain any of the keys or values from ``FEED_TYPES``.

	*name* (``str``) is the name to use when an error occurs.

	Returns a ``list`` containing each *key*-*feed_type* ``tuple``.

		- *key* (``str``) is the query argument key for *feed_type*.

		- *feed_type* (``str``) is the Feed Type ID.
	"""
    if not name:
        name = 'feed_types'

    if not is_sequence(feed_types):
        raise TypeError("{}:{!r} is not a sequence.".format(name, feed_types))

    args = []
    for i, feed_type in enumerate(feed_types):
        feed_type = FEED_TYPES.get(feed_type, feed_type)
        if not isinstance(feed_type, six.string_types):
            raise TypeError("{}[{}]:{!r} is not a str.".format(
                name, i, feed_type))
        elif not feed_type:
            raise ValueError("{}[{}]:{!r} cannot be empty.".format(
                name, i, feed_type))
        feed_type = encode_string(feed_type,
                                  'ASCII',
                                  name="{}[{}]".format(name, i))

        args.append(('FeedTypeList.Type.{}'.format(i + 1), feed_type))

    return args
示例#18
0
def status_args(statuses, name=None):
    """
	Converts the specified Feed Processing Statuses into their respective
	URL query arguments.

	*statuses* (**sequence**) contains each Feed Processing Status
	(``str``). This can contain any of the keys or value from ``PROCESSING_STATUSES``.

	*name* (``str``) is the name to use when an error occurs.

	Returns a ``list`` containing each *key*-*status* ``tuple``.

		- *key* (``str``) is the query argument key for *status*.

		- *status* (``str``) is the Feed Processing Status.
	"""
    if not name:
        name = 'statuses'

    if not is_sequence(statuses):
        raise TypeError("{}:{!r} is not a sequence.".format(name, statuses))

    args = []
    for i, status in enumerate(statuses):
        status = PROCESSING_STATUSES.get(status, status)
        if not isinstance(status, six.string_types):
            raise TypeError("{}[{}]:{!r} is not a str.".format(
                name, i, status))
        elif not status:
            raise ValueError("{}[{}]:{!r} cannot be empty.".format(
                name, i, status))
        status = encode_string(status, 'ASCII', name="{}[{}]".format(name, i))

        args.append(
            ('FeedProcessingStatusList.Status.{}'.format(i + 1), status))

    return args
示例#19
0
def status_args(statuses, name=None):
    """
	Converts the specified Report Processing Status into their respective
	URL query arguments.
	
	*statuses* (**sequence**) contains each Report Processing Status
	(``str``). This contain any keys or values from ``REPORT_STATUSES``.
		
	*name* (``str``) is the name to use when an error occurs.
	
	Returns a ``list`` containing each *key*-*status* ``tuple``.
	
		- *key* (``str``) is the query argument key for *status*.
		
		- *request_id* (``str``) is the Report Processing Status.
	"""
    if not name:
        name = 'statuses'

    if not is_sequence(statuses):
        raise TypeError("{}:{!r} is not a statuses.".format(name, statuses))

    args = []
    for i, status in enumerate(statuses, 0):
        if not isinstance(status, basestring):
            raise TypeError("{}[{}]:{!r} is not a string.".format(
                name, i, status))
        elif not status:
            raise ValueError("{}[{}]:{!r} cannot be empty.".format(
                name, i, status))
        status = encode_string(status, 'ASCII', name="{}[{}]".format(name, i))

        args.append(
            ('ReportProcessingStatusList.Status.{}'.format(i + 1), status))

    return args
示例#20
0
def request_args(requests, name=None):
    """
	Converts the specified Report Request IDs into their respective URL
	query arguments.
	
	*requests* (**sequence**) contains each Report Request ID (``str``).
		
	*name* (``str``) is the name to use when an error occurs.
	
	Returns a ``list`` containing each *key*-*request_id* ``tuple``.
	
		- *key* (``str``) is the query argument key for *request_id*.
		
		- *request_id* (``str``) is the Report Request ID.
	"""
    if not name:
        name = 'requests'

    if not is_sequence(requests):
        raise TypeError("{}:{!r} is not a sequence.".format(name, requests))

    args = []
    for i, request_id in enumerate(requests, 0):
        if not isinstance(request_id, basestring):
            raise TypeError("{}[{}]:{!r} is not a string.".format(
                name, i, request_id))
        elif not request_id:
            raise ValueError("{}[{}]:{!r} cannot be empty.".format(
                name, i, request_id))
        request_id = encode_string(request_id,
                                   'ASCII',
                                   name="{}[{}]".format(name, i))

        args.append(('ReportRequestIdList.Id.{}'.format(i + 1), request_id))

    return args
示例#21
0
    def build_request(self, mws, path, args, body, content_type, debug=None):
        """
		Builds the request.

		.. NOTE:: This should not be called directly. Use *self.request()*.

		*mws* (``MWS``) is the MWS instance.

		*path* (``str``) is the request path.

		*args* contains the query parameters.

		*body* (``str`` or ``file``) contains the body of the request. This
		can be ``None``.

		*content_type* (``str``) is the content type of *body*.

		*debug* (``dict``) is whether debugging information should be
		printed. Default is ``None`` for no debugging.

		- *body* (``bool``) is whether the request body should be printed
		  (``True``), or not (``False``). Default is ``None`` for ``False``.

		- *info* (``bool``) is whether the request args and headers should
		  be printed (``True``), or not (``False``).

		- *url* (``bool``) is whether the generated URL should be printed
		  (``True``), or not (``False``). Default is ``None`` for ``False``.

		Returns a ``tuple`` containing: *method*, the request URL (``str``),
		the request headers (``dict`` or ``None``), and the request body
		(``str``, ``file`` or ``None``).
		"""

        # Before anything else, ensure body is proper data type (if string)
        if body is not None:
            if isinstance(body, six.string_types):
                # Ensure string types are byte-arrays.
                body = six.b(body)

        if debug is None:
            debug = {}

        if not isinstance(mws, MWS):
            raise TypeError("mws:{!r} is not an MWS.".format(mws))

        if isinstance(args, dict):
            args = list(six.iteritems(args))
        elif is_sequence(args):
            args = args[:]
        else:
            raise TypeError(
                "args:{!r} must be a dict or sequence.".format(args))

        # Check for missing and reserved args.
        arg_keys = set([k for k, _v in args])
        missing = self.req_args_required - arg_keys
        if len(missing) > 1:
            raise KeyError("args:{!r} is missing keys: {}.".format(
                args, ", ".join(map(repr, missing))))
        elif missing:
            raise KeyError("args:{!r} is missing key: {!r}.".format(
                args, missing.pop()))
        reserved = self.req_args_sig & arg_keys
        if len(reserved) > 1:
            raise KeyError("args:{!r} cannot have keys: {}.".format(
                args, ", ".join(map(repr, reserved))))
        elif reserved:
            raise KeyError("args:{!r} cannot have key: {!r}.".format(
                args, reserved.pop()))

        if body is not None:
            body_is_str = isinstance(body, six.binary_type)
            body_is_file = callable(getattr(body, 'read', None))
            if not body_is_str and not body_is_file:
                raise TypeError("body:{!r} is not a str or file.".format(body))

            if not isinstance(content_type, six.string_types):
                raise TypeError(
                    "content_type:{!r} is not a str.".format(content_type))
            elif not content_type:
                raise ValueError(
                    "content_type:{!r} cannot be empty.".format(content_type))

        if path is not None and not isinstance(path, six.string_types):
            raise TypeError("path:{!r} is not a str.".format(path))

        # Query.
        args += [('SignatureMethod', SIGNATURE_METHODS[self.sig_method]),
                 ('SignatureVersion', self.sig_version)]
        args = sorted(args, key=self.sort_args_key)
        query = "&".join(("{}={}".format(
            six.moves.urllib.parse.quote(str(k), self.req_args_safe_chars),
            six.moves.urllib.parse.quote(str(v), self.req_args_safe_chars)))
                         for k, vals in args
                         for v in (vals if is_sequence(vals) else [vals]))

        # Signature
        method = "GET" if body is None else "POST"
        result = six.moves.urllib.parse.urlparse(mws.endpoint)
        domain = result.netloc or result.path
        path = six.moves.urllib.parse.quote(
            os.path.normpath('/' + path.lstrip('/'))) if path else "/"
        sig = self.sign_request(mws.secret_key, method, domain, path, query)

        # URL.
        url = "{host}{path}?{query}&Signature={sig}".format(
            host=mws.endpoint,
            path=path,
            query=query,
            sig=six.moves.urllib.parse.quote(sig, safe='/'))

        # Headers.
        headers = {'User-Agent': mws.user_agent}

        if body is not None:
            if body_is_str:
                body_len = len(body)
                body_md5 = base64.b64encode(hashlib.md5(body).digest())
            elif body_is_file:
                if callable(getattr(body, 'seek', None)) and callable(
                        getattr(body, 'tell', None)):
                    # MD5 body and get length.
                    pos = body.tell()
                    md5 = hashlib.md5()
                    while True:
                        chunk = body.read(2**16)
                        if not chunk:
                            break
                        md5.update(chunk)
                    body_len = body.tell() - pos
                    body_md5 = base64.b64encode(md5.digest())
                    body.seek(pos, os.SEEK_SET)

                else:
                    body = body.read()
                    body_len = len(body)
                    body_md5 = base64.b64encode(hashlib.md5(body).digest())
                    body_is_file = False

            if body_len > mws.max_size:
                raise ValueError(
                    "body length:{!r} cannot be greater than {}.".format(
                        body_len, mws.max_size))

            headers['Content-Type'] = content_type
            headers['Content-Length'] = body_len
            headers['Content-MD5'] = body_md5
        else:
            body_len = None

        # Debug info.
        if debug:
            if debug.get('url', False):
                print("URL ({}:{})".format(url.__class__.__name__, len(url)))
                print("--------")
                print(url)
                print("--------")
            if debug.get('info', False):
                print("Args ({})".format(len(args)))
                print("---------")
                pprint.pprint(args)
                print("---------")
                print("Headers ({})".format(len(headers)))
                print("------------")
                pprint.pprint(headers)
                print("------------")
            if debug.get('body', False) or debug.get('info', False):
                print("Body ({}:{})".format(body.__class__.__name__, body_len))
            if debug.get('body', False):
                print("-" * 20)
                if body_is_file:
                    pos = body.tell()
                    print(body.read())
                    body.seek(pos, os.SEEK_SET)
                else:
                    print(body)
                print("-" * 20)

        return method, url, headers, body
示例#22
0
	def list_orders(self, created_after=None, updated_after=None, order_statuses=None, marketplaces=None):
		"""
		Requests the list of Orders that match the specified criteria.

		Either *created_after* or *updated_after* must be set, but not both.

		*created_after* (``datetime.datetime`` or ``float``) is used to
		select orders that were created at/after the specified date-time.

		*updated_after* (``datetime.datetime`` or ``float``) is used to
		select orders that were updated at/after the specified date-time.

		The query can be further refined by specifying any of the following:

		*order_statuses* (**sequence**) contains each Order Status (``str``)
		to filter the list of orders to list. Default is ``None`` for all
		Order Statuses.

		.. SEEALSO:: ``ORDER_STATUSES``.

		*marketplaces* (**sequence**) contains the ID (``str``) of each
		Amazon Marketplace to list orders from. Default is ``None`` for all
		Amazon Marketplaces.

		Returns the response XML (``str``).
		"""
		if (created_after is None and updated_after is None) or (created_after is not None and updated_after is not None):
			raise ValueError("Either created_after:{!r} or updated_after:{!r} must be set, but not both.".format(created_after, updated_after))

		args = self.new_args()

		if created_after is not None:
			args['CreatedAfter'] = datetime_to_iso8601(created_after, name='created_after')

		if updated_after is not None:
			args['LastUpdatedAfter'] = datetime_to_iso8601(updated_after, name='updated_after')

		if order_statuses is not None:
			if not is_sequence(order_statuses):
				raise TypeError("order_statuses:{!r} is not a sequence.".format(order_statuses))
			elif not order_statuses:
				raise ValueError("order_statuses:{!r} cannot be empty.".format(order_statuses))
			amazon_statuses = []
			for i, status in enumerate(order_statuses):
				status = ORDER_STATUSES.get(status, status)
				if not isinstance(status, basestring):
					raise TypeError("order_statuses[{}]:{!r} is not a string.".format(i, status))
				elif not status:
					raise ValueError("order_statuses[{}]:{!r} cannot be empty.".format(i, status))
				try:
					status = status.encode('ASCII')
				except UnicodeDecodeError as e:
					e.reason += " for order_statuses[{}]".format(i)
					e.args = e.args[:4] + (e.reason,)
					raise e
				amazon_statuses.append(status)
			args['OrderStatus'] = amazon_statuses

		if marketplaces is not None:
			if not is_sequence(marketplaces):
				raise TypeError("marketplaces:{!r} is not a sequence.".format(marketplaces))
			elif not marketplaces:
				raise ValueError("marketplaces:{!r} cannot be empty.".format(marketplaces))
			for i, market in enumerate(marketplaces):
				if not isinstance(market, basestring):
					raise TypeError("marketplaces[{}]:{!r} is not a string.".format(i, market))
				elif not market:
					raise ValueError("marketplaces[{}]:{!r} cannot be empty.".format(i, market))
				try:
					market = market.encode('ASCII')
				except UnicodeDecodeError as e:
					e.reason += " for marketplaces[{}]".format(i)
					e.args = e.args[:4] + (e.reason,)
					raise e
			args['MarketplaceId'] = marketplaces

		return self.send_request('ListOrders', args)
示例#23
0
	def build_request(self, mws, path, args, body, content_type, debug=None):
		"""
		Builds the request.

		.. NOTE:: This should not be called directly. Use *self.request()*.

		*mws* (``MWS``) is the MWS instance.

		*path* (``str``) is the request path.

		*args* contains the query parameters.

		*body* (``str`` or ``file``) contains the body of the request. This
		can be ``None``.

		*content_type* (``str``) is the content type of *body*.

		*debug* (``dict``) is whether debugging information should be
		printed. Default is ``None`` for no debugging.

		- *body* (``bool``) is whether the request body should be printed
		  (``True``), or not (``False``). Default is ``None`` for ``False``.

		- *info* (``bool``) is whether the request args and headers should
		  be printed (``True``), or not (``False``).

		- *url* (``bool``) is whether the generated URL should be printed
		  (``True``), or not (``False``). Default is ``None`` for ``False``.

		Returns a ``tuple`` containing: *method*, the request URL (``str``),
		the request headers (``dict`` or ``None``), and the request body
		(``str``, ``file`` or ``None``).
		"""
		
		# Before anything else, ensure body is proper data type (if string)
		if body is not None:
			if isinstance(body, six.string_types):
				# Ensure string types are byte-arrays.
				body = six.b(body)

		if debug is None:
			debug = {}

		if not isinstance(mws, MWS):
			raise TypeError("mws:{!r} is not an MWS.".format(mws))

		if isinstance(args, dict):
			args = list(six.iteritems(args))
		elif is_sequence(args):
			args = args[:]
		else:
			raise TypeError("args:{!r} must be a dict or sequence.".format(args))

		# Check for missing and reserved args.
		arg_keys = set([k for k, _v in args])
		missing = self.req_args_required - arg_keys
		if len(missing) > 1:
			raise KeyError("args:{!r} is missing keys: {}.".format(args, ", ".join(map(repr, missing))))
		elif missing:
			raise KeyError("args:{!r} is missing key: {!r}.".format(args, missing.pop()))
		reserved = self.req_args_sig & arg_keys
		if len(reserved) > 1:
			raise KeyError("args:{!r} cannot have keys: {}.".format(args, ", ".join(map(repr, reserved))))
		elif reserved:
			raise KeyError("args:{!r} cannot have key: {!r}.".format(args, reserved.pop()))

		if body is not None:
			body_is_str = isinstance(body, six.binary_type)
			body_is_file = callable(getattr(body, 'read', None))
			if not body_is_str and not body_is_file:
				raise TypeError("body:{!r} is not a str or file.".format(body))

			if not isinstance(content_type, six.string_types):
				raise TypeError("content_type:{!r} is not a str.".format(content_type))
			elif not content_type:
				raise ValueError("content_type:{!r} cannot be empty.".format(content_type))

		if path is not None and not isinstance(path, six.string_types):
			raise TypeError("path:{!r} is not a str.".format(path))

		# Query.
		args += [
			('SignatureMethod', SIGNATURE_METHODS[self.sig_method]),
			('SignatureVersion', self.sig_version)
		]
		args = sorted(args, key=self.sort_args_key)
		query = "&".join((
			"{}={}".format(six.moves.urllib.parse.quote(str(k), self.req_args_safe_chars), six.moves.urllib.parse.quote(str(v), self.req_args_safe_chars))
		) for k, vals in args for v in (vals if is_sequence(vals) else [vals]))

		# Signature
		method = "GET" if body is None else "POST"
		result = six.moves.urllib.parse.urlparse(mws.endpoint)
		domain = result.netloc or result.path
		path = six.moves.urllib.parse.quote(os.path.normpath('/' + path.lstrip('/'))) if path else "/"
		sig = self.sign_request(mws.secret_key, method, domain, path, query)

		# URL.
		url = "{host}{path}?{query}&Signature={sig}".format(
			host=mws.endpoint,
			path=path,
			query=query,
			sig=six.moves.urllib.parse.quote(sig, safe='/')
		)

		# Headers.
		headers = {
			'User-Agent': mws.user_agent
		}

		if body is not None:
			if body_is_str:
				body_len = len(body)
				body_md5 = base64.b64encode(hashlib.md5(body).digest())
			elif body_is_file:
				if callable(getattr(body, 'seek', None)) and callable(getattr(body, 'tell', None)):
					# MD5 body and get length.
					pos = body.tell()
					md5 = hashlib.md5()
					while True:
						chunk = body.read(2**16)
						if not chunk:
							break
						md5.update(chunk)
					body_len = body.tell() - pos
					body_md5 = base64.b64encode(md5.digest())
					body.seek(pos, os.SEEK_SET)

				else:
					body = body.read()
					body_len = len(body)
					body_md5 = base64.b64encode(hashlib.md5(body).digest())
					body_is_file = False

			if body_len > mws.max_size:
				raise ValueError("body length:{!r} cannot be greater than {}.".format(body_len, mws.max_size))

			headers['Content-Type'] = content_type
			headers['Content-Length'] = body_len
			headers['Content-MD5'] = body_md5

		# Debug info.
		if debug:
			if debug.get('url', False):
				print("URL ({}:{})".format(url.__class__.__name__, len(url)))
				print("--------")
				print(url)
				print("--------")
			if debug.get('info', False):
				print("Args ({})".format(len(args)))
				print("---------")
				pprint.pprint(args)
				print("---------")
				print("Headers ({})".format(len(headers)))
				print("------------")
				pprint.pprint(headers)
				print("------------")
			if debug.get('body', False) or debug.get('info', False):
				print("Body ({}:{})".format(body.__class__.__name__, body_len))
			if debug.get('body', False):
				print("-"*20)
				if body_is_file:
					pos = body.tell()
					print(body.read())
					body.seek(pos, os.SEEK_SET)
				else:
					print(body)
				print("-"*20)

		return method, url, headers, body