diff --git a/.gitignore b/.gitignore index 50d2de3..4f100ae 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,27 @@ run.py run3.py *.orig .eggs/* -.cache/v/cache/lastfailed -pylint_report.txt +.cache/v/cache/lastfailed +pylint_report.txt + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ diff --git a/.travis.yml b/.travis.yml index 0a4416f..6b801e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,5 +10,7 @@ python: install: - pip install . - pip install -r requirements-test.txt -# command to run tests -script: nosetests + +script: py.test --cov=wordpress tests.py + +after_success: codecov diff --git a/README.rst b/README.rst index f6a6fe1..997d7d1 100644 --- a/README.rst +++ b/README.rst @@ -65,7 +65,7 @@ If you have installed from source, then you can test with unittest: .. code-block:: bash pip install -r requirements-test.txt - python -m unittest -v tests + py.test --cov=wordpress tests.py Getting started --------------- diff --git a/requirements-test.txt b/requirements-test.txt index 34cbeb8..cbb8b40 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,4 +1,7 @@ -r requirements.txt httmock==1.2.3 -nose==1.3.7 six +pytest==3.3.1 +pytest-cov==2.5.1 +coverage +codecov diff --git a/wordpress/__init__.py b/wordpress/__init__.py index abd7727..b6a4ff1 100644 --- a/wordpress/__init__.py +++ b/wordpress/__init__.py @@ -10,7 +10,7 @@ """ __title__ = "wordpress" -__version__ = "1.2.6" +__version__ = "1.2.8" __author__ = "Claudio Sanches @ WooThemes, forked by Derwent" __license__ = "MIT" diff --git a/wordpress/api.py b/wordpress/api.py index bf61ce6..eb99bc2 100644 --- a/wordpress/api.py +++ b/wordpress/api.py @@ -3,18 +3,24 @@ """ Wordpress API Class """ - -__title__ = "wordpress-api" - -# from requests import request +from __future__ import unicode_literals import logging from json import dumps as jsonencode -from wordpress.auth import BasicAuth, OAuth, OAuth_3Leg +from wordpress.auth import BasicAuth, OAuth, OAuth_3Leg, NoAuth from wordpress.helpers import StrUtils, UrlUtils from wordpress.transport import API_Requests_Wrapper +try: + UNICODE_EXISTS = bool(type(unicode)) +except NameError: + unicode = lambda s: str(s) + +__title__ = "wordpress-api" + + + class API(object): """ API Class """ @@ -34,9 +40,12 @@ def __init__(self, url, consumer_key, consumer_secret, **kwargs): auth_class = BasicAuth elif kwargs.get('oauth1a_3leg'): auth_class = OAuth_3Leg + elif kwargs.get('no_auth'): + auth_class = NoAuth if kwargs.get('version', '').startswith('wc') and kwargs.get('oauth1a_3leg'): - self.logger.warn("WooCommerce JSON Api does not seem to support 3leg") + self.logger.warn( + "WooCommerce JSON Api does not seem to support 3leg") self.auth = auth_class(**auth_kwargs) @@ -102,17 +111,17 @@ def request_post_mortem(self, response=None): if 'code' in response_json or 'message' in response_json: reason = u" - ".join([ - unicode(response_json.get(key)) for key in ['code', 'message', 'data'] \ + unicode(response_json.get(key)) for key in ['code', 'message', 'data'] if key in response_json ]) if 'code' == 'rest_user_invalid_email': remedy = "Try checking the email %s doesn't already exist" % \ - request_body.get('email') + request_body.get('email') elif 'code' == 'json_oauth1_consumer_mismatch': remedy = "Try deleting the cached credentials at %s" % \ - self.auth.creds_store + self.auth.creds_store elif 'code' == 'woocommerce_rest_cannot_view': if not self.auth.query_string_auth: @@ -145,26 +154,29 @@ def request_post_mortem(self, response=None): header_api_url = StrUtils.eviscerate(header_api_url, '/') if header_api_url and requester_api_url\ - and header_api_url != requester_api_url: + and header_api_url != requester_api_url: reason = "hostname mismatch. %s != %s" % ( header_api_url, requester_api_url ) header_url = StrUtils.eviscerate(header_api_url, '/') - header_url = StrUtils.eviscerate(header_url, self.requester.api) + header_url = StrUtils.eviscerate( + header_url, self.requester.api) header_url = StrUtils.eviscerate(header_url, '/') remedy = "try changing url to %s" % header_url msg = "API call to %s returned \nCODE: %s\nRESPONSE:%s \nHEADERS: %s\nREQ_BODY:%s" % ( request_url, - str(response.status_code), + unicode(response.status_code), UrlUtils.beautify_response(response), - str(response_headers), - str(request_body)[:1000] + unicode(response_headers), + unicode(request_body.encode('utf-8'))[:1000] ) + if reason: - msg += "\nBecause of %s" % reason + msg += "\nBecause of %s" % (str(reason.encode('utf8'))) if remedy: - msg += "\n%s" % remedy + msg += "\n%s" % (str(remedy)) + raise UserWarning(msg) def __request(self, method, endpoint, data, **kwargs): @@ -174,7 +186,8 @@ def __request(self, method, endpoint, data, **kwargs): endpoint_url = self.auth.get_auth_url(endpoint_url, method, **kwargs) auth = self.auth.get_auth() - content_type = kwargs.get('headers', {}).get('content-type', 'application/json') + content_type = kwargs.get('headers', {}).get( + 'content-type', 'application/json') if data is not None and content_type.startswith('application/json'): data = jsonencode(data, ensure_ascii=False).encode('utf-8') diff --git a/wordpress/auth.py b/wordpress/auth.py index af4b7bd..4830ed3 100644 --- a/wordpress/auth.py +++ b/wordpress/auth.py @@ -94,6 +94,15 @@ def get_auth(self): return HTTPBasicAuth(self.consumer_key, self.consumer_secret) +class NoAuth(Auth): + """ + Just a dummy Auth object to allow header based + authorization per request + """ + def get_auth_url(self, endpoint_url, method, **kwargs): + return endpoint_url + + class OAuth(Auth): """ Signs string with oauth consumer_key and consumer_secret """ oauth_version = '1.0' diff --git a/wordpress/transport.py b/wordpress/transport.py index 3262070..7df25f2 100644 --- a/wordpress/transport.py +++ b/wordpress/transport.py @@ -33,6 +33,7 @@ def __init__(self, url, **kwargs): self.timeout = kwargs.get("timeout", 5) self.verify_ssl = kwargs.get("verify_ssl", True) self.session = Session() + self.headers = kwargs.get("headers", {}) @property def is_ssl(self): @@ -84,6 +85,10 @@ def request(self, method, url, auth=None, params=None, data=None, **kwargs): "user-agent": "Wordpress API Client-Python/%s" % __version__, "accept": "application/json" } + headers = SeqUtils.combine_ordered_dicts( + headers, + self.headers + ) if data is not None: headers["content-type"] = "application/json;charset=utf-8" headers = SeqUtils.combine_ordered_dicts(