diff --git a/README.md b/README.md index e1061d4..59c424d 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ python setup.py install In order to use the client, you must have both an API key and an API secret. To obtain your key and secret, you need to first create an account at https://www.semantics3.com/ -You can access your API access credentials from the user dashboard at https://www.semantics3.com/dashboard/applications +You can access your API access credentials from the user dashboard at https://dashboard.semantics3.com. ### Setup Work @@ -43,8 +43,8 @@ from semantics3 import Products # Set up a client to talk to the Semantics3 API using your Semantics3 API Credentials sem3 = Products( - api_key = "SEM3xxxxxxxxxxxxxxxxxxxxxx", - api_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + api_key=os.environ['SEMANTICS3_API_KEY'], + api_secret=os.environ['SEMANTICS3_API_SECRET'] ) ``` @@ -91,9 +91,34 @@ for i in sem3.iter(): print "We are at page = %s" % page_no print "The results for this page are:" print i - + sleep(1) #respect rate limit +``` + +### Request Timeout + +The RealTime API has a hard server-side timeout of **60s** (up to **120s** for some customers) by default after which the client request will be aborted. You can +override this behaviour by setting a client-side timeout value as shown below: + +```python +import os +from requests.exceptions import ReadTimeout, ConnectTimeout +from semantics3 import Products + +sem3 = Products( + api_key=os.environ['SEMANTICS3_API_KEY'], + api_secret=os.environ['SEMANTICS3_API_SECRET'], + timeout=5 +) + +try: + sem3.run_query('realtime/skus', 'GET', { 'url': 'https://www.walmart.com/ip/325408104' }) +except (ReadTimeout, ConnectTimeout): + print('request timed out in 5s') + ``` + + ### UPC Query Running a UPC/EAN/GTIN query is as simple as running a search query: @@ -159,7 +184,7 @@ params = { webhook_uri : "http://mydomain.com/webhooks-callback-url" } -webhook = sem3.run_query("webhooks", params, "POST") +webhook = sem3.run_query("webhooks", "POST", params) print webhook["id"] print webhook["webhook_uri"] ``` diff --git a/README.rst b/README.rst index bffac76..f4293d5 100644 --- a/README.rst +++ b/README.rst @@ -37,8 +37,7 @@ Getting Started In order to use the client, you must have both an API key and an API secret. To obtain your key and secret, you need to first create an account at https://www.semantics3.com/ You can access your API access -credentials from the user dashboard at -https://www.semantics3.com/dashboard/applications +credentials from the user dashboard at https://dashboard.semantics3.com. Setup Work ~~~~~~~~~~ diff --git a/semantics3/products.py b/semantics3/products.py index 6bc7452..a07d6b0 100644 --- a/semantics3/products.py +++ b/semantics3/products.py @@ -5,8 +5,8 @@ class Products(Semantics3Request): - def __init__(self, api_key, api_secret, api_base='https://api.semantics3.com/v1/'): - Semantics3Request.__init__(self, api_key, api_secret, 'products', api_base) + def __init__(self, api_key, api_secret, api_base='https://api.semantics3.com/v1/', timeout=120): + Semantics3Request.__init__(self, api_key, api_secret, 'products', api_base, timeout) def get_products(self): return self.get() diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 725c997..c6657e0 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -1,5 +1,6 @@ import json from requests_oauthlib import OAuth1Session +from url_normalize import url_normalize try: import urllib.parse as urllib @@ -14,7 +15,7 @@ class Semantics3Request: - def __init__(self, api_key=None, api_secret=None, endpoint=None, api_base='https://api.semantics3.com/v1/'): + def __init__(self, api_key=None, api_secret=None, endpoint=None, api_base='https://api.semantics3.com/v1/', timeout=120): if api_key is None: raise Semantics3Error( 'API Credentials Missing', @@ -35,16 +36,26 @@ def __init__(self, api_key=None, api_secret=None, endpoint=None, api_base='https self.query_result = None self.cache_size = 10 self.api_base = api_base + self.timeout = timeout def fetch(self, method, endpoint, params): - api_endpoint = self.api_base + endpoint - content = self.oauth.request( - method, - api_endpoint, - params = params, - headers={'User-Agent':'Semantics3 Python Lib/0.2'} - ) - print(content) + api_endpoint = url_normalize(self.api_base + endpoint) + if method.lower() in ['get', 'delete']: + content = self.oauth.request( + method, + api_endpoint, + params = params, + headers={'User-Agent':'Semantics3 Python Lib/0.2'}, + timeout=self.timeout + ) + else: + content = self.oauth.request( + method, + api_endpoint, + data = json.dumps(params), + headers={'User-Agent':'Semantics3 Python Lib/0.2', 'Content-Type':'application/json'}, + timeout=self.timeout + ) return content def remove(self, endpoint, *fields): @@ -104,7 +115,7 @@ def iter(self): self.run_query() def query(self, method, endpoint, kwargs): - if method == "GET": + if method.lower() == "get": params = { 'q' : json.dumps(kwargs) } else: params = kwargs @@ -113,7 +124,7 @@ def query(self, method, endpoint, kwargs): response_json = response.json() except: raise Exception("Malformed JSON") - + if response.status_code < 400: return response.json() else: @@ -124,7 +135,7 @@ def query(self, method, endpoint, kwargs): def run_query(self, endpoint=None, method='GET', params=None): endpoint = endpoint or self.endpoint - if method == "GET": + if method.lower() == "get": try: query = self.data_query[endpoint] except KeyError: @@ -141,7 +152,7 @@ def run_query(self, endpoint=None, method='GET', params=None): params ) return self.query_result - + def get(self, endpoint=None): return self.run_query(endpoint) diff --git a/setup.py b/setup.py index 9bedda0..da0f211 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,7 @@ install_requires = [ 'requests-oauthlib >= 0.4.0', + 'url-normalize' ] def read(fname): try: @@ -20,9 +21,9 @@ def read(fname): setup( name="semantics3", - version="0.2", - author="Shawn Tan", - author_email="shawn@semantics3.com", + version="0.3.9", + author="Shawn Tan, Abishek Bhat", + author_email="abishek@semantics3.com", description=("Semantics3 Products API"), license="MIT", keywords="api ecommerce products", diff --git a/tests/test_product.py b/tests/test_product.py index 8174734..d09f478 100644 --- a/tests/test_product.py +++ b/tests/test_product.py @@ -1,9 +1,10 @@ from semantics3 import Products import unittest +from os import environ sem3 = Products( - api_key = "", - api_secret = "" + api_key = environ["SEM3_API_KEY"], + api_secret = environ["SEM3_API_SECRET"] ) diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py index 34e1198..b50b123 100644 --- a/tests/test_webhooks.py +++ b/tests/test_webhooks.py @@ -1,41 +1,69 @@ -from semantics3 import Products +from semantics3 import Semantics3Request import unittest +from os import environ -sem3 = Products( - api_key = "", - api_secret = "" +sem3 = Semantics3Request( + api_key = environ["SEM3_API_KEY"], + api_secret = environ["SEM3_API_SECRET"] ) -class TestWebhooksAPI(unittest.TestCase): +class TestWebhoOKsAPI(unittest.TestCase): - """Docstring for TestWebhooks. """ + """Docstring for TestWebhoOKs. """ def test_webhook_registration(self): """@todo: Docstring for test_webhook_registration. :returns: @todo """ - result = sem3.run_query('webhooks', "POST", {"webhook_uri" : "http://148.251.44.168:5000"}) - self.assertIn('created', result) - + result = sem3.run_query('webhooks', "POST", {"webhook_uri" : "https://semantics3-basic-webhook-receiver-11ozacc07xtw.runkit.sh/"}) + self.assertIn('created', result["results"]) + def test_get_webhooks(self): """@todo: Docstring for test_get_webhooks. :returns: @todo """ webhooks = sem3.run_query('webhooks', "GET") - self.assertEqual(webhooks['status'], 'ok') - + self.assertEqual(webhooks['code'], 'OK') + + def test_register_event(self): + """@todo: Docstring for function. + + :returns: @todo + + """ + webhooks = sem3.run_query('webhooks', "GET") + if len(webhooks['results']): + webhook_id = webhooks['data'][0]['id'] + params = { + "type": "price.change", + "product": { + "sem3_id": "1QZC8wchX62eCYS2CACmka" + }, + "constraints" : { + "gte" : 10, + "lte" : 100 + } + } + response = sem3.run_query('webhooks/%s/events' % webhook_id, "POST", params) + self.assertEqual(response['code'], 'OK') + del params['constraints'] + response1 = sem3.run_query('webhooks/%s/events' % webhook_id, "POST", params) + self.assertEqual(response1['code'], 'OK') + else: + self.assertEqual(webhooks['code'], 'OK') + def test_delete_webhook(self): """@todo: Docstring for test_delete_webhook. :returns: @todo """ webhooks = sem3.run_query('webhooks', "GET") - if len(webhooks['data']): - webhook_id = webhooks['data'][0]['id'] + if len(webhooks['results']): + webhook_id = webhooks['results'][0]['id'] response = sem3.run_query('webhooks/%s' % webhook_id, "DELETE") - self.assertEqual(response['status'], 'ok') + self.assertEqual(response['code'], 'OK') else: - self.assertEqual(webhooks['status'], 'ok') + self.assertEqual(webhooks['code'], 'OK')