Skip to content
This repository was archived by the owner on Jan 4, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# mws
This is a fork and continuation of https://github.com/czpython/python-amazon-mws.
This is a fork and continuation of https://github.com/czpython/python-amazon-mws with preliminary Python 2/3 support.

Install from PyPI with `pip install mws`.

Expand Down
6 changes: 2 additions & 4 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys, os

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
Expand Down Expand Up @@ -48,9 +46,9 @@
# built documents.
#
# The short X.Y version.
version = '0.6'
version = '0.7'
# The full version, including alpha/beta/rc tags.
release = '0.6'
release = '0.7'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
4 changes: 2 additions & 2 deletions mws/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
__version__ = '0.6'
from __future__ import absolute_import

from mws import *
from .mws import *
70 changes: 43 additions & 27 deletions mws/mws.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Basic interface to Amazon MWS
# Based on http://code.google.com/p/amazon-mws-python
#
from __future__ import absolute_import

import urllib
import base64
import hashlib
import hmac
import base64
import utils
import re
from time import gmtime, strftime

from requests import request
from requests.exceptions import HTTPError

from . import utils

try:
from urllib.parse import quote
except ImportError:
from urllib import quote
try:
from xml.etree.ElementTree import ParseError as XMLError
except ImportError:
from xml.parsers.expat import ExpatError as XMLError
from time import strftime, gmtime

from requests import request
from requests.exceptions import HTTPError


__all__ = [
Expand Down Expand Up @@ -64,15 +65,19 @@ def calc_md5(string):
"""
md = hashlib.md5()
md.update(string)
return base64.encodestring(md.digest()).strip('\n')
return base64.encodebytes(md.digest()).strip('\n')


def remove_empty(d):
"""Helper function that removes all keys from a dictionary (d), that have an empty value.

Args:
d (dict)

Return:
dict
"""
Helper function that removes all keys from a dictionary (d),
that have an empty value.
"""
for key in d.keys():
for key in set(d.keys()):
if not d[key]:
del d[key]
return d
Expand All @@ -88,7 +93,7 @@ def __init__(self, xml, rootkey=None):
self.original = xml
self._rootkey = rootkey
self._mydict = utils.xml2dict().fromstring(remove_namespace(xml))
self._response_dict = self._mydict.get(self._mydict.keys()[0],
self._response_dict = self._mydict.get(list(self._mydict.keys())[0],
self._mydict)

@property
Expand Down Expand Up @@ -180,9 +185,9 @@ def make_request(self, extra_data, method="GET", **kwargs):
if self.auth_token:
params['MWSAuthToken'] = self.auth_token
params.update(extra_data)
request_description = '&'.join(['%s=%s' % (k, urllib.quote(params[k], safe='-_.~').encode('utf-8')) for k in sorted(params)])
request_description = '&'.join(['%s=%s' % (k, quote(params[k], safe='-_.~')) for k in sorted(params)])
signature = self.calc_signature(method, request_description)
url = '%s%s?%s&Signature=%s' % (self.domain, self.uri, request_description, urllib.quote(signature))
url = '%s%s?%s&Signature=%s' % (self.domain, self.uri, request_description, quote(signature))
headers = {'User-Agent': 'python-amazon-mws/0.0.1 (Language=Python)'}
headers.update(kwargs.get('extra_headers', {}))

Expand All @@ -196,16 +201,18 @@ def make_request(self, extra_data, method="GET", **kwargs):
# When retrieving data from the response object,
# be aware that response.content returns the content in bytes while response.text calls
# response.content and converts it to unicode.
data = response.content

data = response.content
# I do not check the headers to decide which content structure to server simply because sometimes
# Amazon's MWS API returns XML error responses with "text/plain" as the Content-Type.
try:
parsed_response = DictWrapper(data, extra_data.get("Action") + "Result")
except TypeError: # raised when using Python 3 and trying to remove_namespace()
parsed_response = DictWrapper(response.text, extra_data.get("Action") + "Result")
except XMLError:
parsed_response = DataWrapper(data, response.headers)

except HTTPError, e:
except HTTPError as e:
error = MWSError(str(e.response.text))
error.response = e.response
raise error
Expand All @@ -224,9 +231,18 @@ def get_service_status(self):

def calc_signature(self, method, request_description):
"""Calculate MWS signature to interface with Amazon

Args:
method (str)
request_description (str)
"""
sig_data = method + '\n' + self.domain.replace('https://', '').lower() + '\n' + self.uri + '\n' + request_description
return base64.b64encode(hmac.new(str(self.secret_key), sig_data, hashlib.sha256).digest())
sig_data = '\n'.join([
method,
self.domain.replace('https://', '').lower(),
self.uri,
request_description
])
return base64.b64encode(hmac.new(self.secret_key.encode(), sig_data.encode(), hashlib.sha256).digest())

def get_timestamp(self):
"""
Expand Down Expand Up @@ -398,9 +414,9 @@ def get_report_schedule_count(self, types=()):
class Orders(MWS):
""" Amazon Orders API """

URI = "/Orders/2011-01-01"
VERSION = "2011-01-01"
NS = '{https://mws.amazonservices.com/Orders/2011-01-01}'
URI = "/Orders/2013-09-01"
VERSION = "2013-09-01"
NS = '{https://mws.amazonservices.com/Orders/2013-09-01}'

def list_orders(self, marketplaceids, created_after=None, created_before=None, lastupdatedafter=None,
lastupdatedbefore=None, orderstatus=(), fulfillment_channels=(),
Expand Down
4 changes: 3 additions & 1 deletion mws/offamazonpayments.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import

from .mws import MWS


Expand Down Expand Up @@ -171,4 +174,3 @@ def close_order_reference(self, order_ref):
AmazonOrderReferenceId=order_ref
)
)

3 changes: 2 additions & 1 deletion mws/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

@author: pierre
"""
from __future__ import absolute_import

import xml.etree.ElementTree as ET
import re
import xml.etree.ElementTree as ET


class object_dict(dict):
Expand Down
5 changes: 5 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
requests

# dev requirements
pypandoc==1.3.3
sphinx==1.4.8
20 changes: 16 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
# -*- coding: utf-8 -*-
short_description = 'Python library for interacting with the Amazon MWS API'
try:
from pypandoc import convert
except (ImportError, OSError): # either pypandoc or pandoc isn't installed
long_description = "See README.md"
else:
long_description = convert("README.md", 'rst')

from setuptools import setup

setup(
name='mws',
version='0.6',
version='0.7',
maintainer="James Hiew",
maintainer_email="james@hiew.net",
url="http://github.com/jameshiew/mws",
description='A python interface for Amazon MWS',
description=short_description,
long_description=long_description,
packages=['mws'],
install_requires=[
'requests'
Expand All @@ -23,11 +32,14 @@
'Topic :: Software Development',
'Topic :: Software Development :: Libraries :: Application Frameworks',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
],
platforms=['OS Independent'],
license='LICENSE.txt',
license='Unlicense',
include_package_data=True,
zip_safe=False
)