From bdd5e3dda4c922def6d558a7cd0961b09cd9e5a0 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Wed, 26 Feb 2014 22:27:10 -0800 Subject: [PATCH 01/48] Modified repo. --- .gitignore | 2 +- README.md | 198 ----------------------------------------------------- README.rst | 0 setup.py | 12 ++-- 4 files changed, 9 insertions(+), 203 deletions(-) delete mode 100644 README.md delete mode 100644 README.rst diff --git a/.gitignore b/.gitignore index ae11db0..2d22aea 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ *.swp *.egg-info dist -build \ No newline at end of file +build diff --git a/README.md b/README.md deleted file mode 100644 index 9e81756..0000000 --- a/README.md +++ /dev/null @@ -1,198 +0,0 @@ -# semantics3 -semantics3 is a python client for accessing the Semantics3 Products API, which provides structured information, including pricing histories, for a large number of products. -See https://www.semantics3.com for more information. - -Quickstart guide: https://www.semantics3.com/quickstart -API documentation can be found at https://www.semantics3.com/docs/ - -## Installation -semantics3 can be installed through pypi: - -```bash -pip install semantics3 -``` - -To install the latest source from the repository - -```bash -git clone https://github.com/Semantics3/semantics3-python.git -cd semantics3-python -python setup.py install -``` - -## Requirements -* requests-oauthlib - -## 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 - -### Setup Work - -Let's lay the groundwork. - -```python -from semantics3 import Products - -# Set up a client to talk to the Semantics3 API using your Semantics3 API Credentials -products = Products( - api_key = "SEM3xxxxxxxxxxxxxxxxxxxxxx", - api_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -) -``` - -### First Query aka 'Hello World': - -Let's make our first query! For this query, we are going to search for all Toshiba products that fall under the category of "Computers and Accessories", whose cat_id is 4992. - -```python -# Build the query -products.products_field( "cat_id", 4992 ) -products.products_field( "brand", "Toshiba" ) - -# Make the query -results = products.get_products(); -#or -results = products.get() - -# View the results of the query -print results -``` - -## Examples - -The following examples show you how to interface with some of the core functionality of the Semantics3 Products API. For more detailed examples check out the Quickstart guide: https://www.semantics3.com/quickstart - -### Explore the Category Tree - -In this example we are going to be accessing the categories endpoint. We are going to be specifically exploiring the "Computers and Accessories" category, which has a cat_id of 4992. For more details regarding our category tree and associated cat_ids check out our API docs at https://www.semantics3.com/docs - -```python -# Build the query -products.categories_field( "cat_id", 4992 ); - -# Execute the query -results = products.get_categories(); - -# View the results of the query -print results -``` - -### Nested Search Query - -You can intuitively construct all your complex queries but just repeatedly using the products_field() or add() methods. -Here is how we translate the following JSON query: - -```javascript -{ - "cat_id" : 4992, - "brand" : "Toshiba", - "weight" : { "gte":1000000, "lt":1500000 }, - "sitedetails" : { - "name" : "newegg.com", - "latestoffers" : { - "currency": "USD", - "price" : { "gte" : 100 } - } - } -} -``` - - -This query returns all Toshiba products within a certain weight range narrowed down to just those that retailed recently on newegg.com for >= USD 100. - -```python -# Build the query -products = Products( api_key, api_secret ) -products.products_field( "cat_id", 4992 ) -products.products_field( "brand", "Toshiba" ) -products.products_field( "weight", "gte", 1000000 ) -products.products_field( "weight", "lt", 1500000 ) -products.products_field( "sitedetails", "name", "newegg.com" ) -products.products_field( "sitedetails", "latestoffers", "currency", "USD" ) -products.products_field( "sitedetails", "latestoffers", "price", "gte", 100 ) -# Let's make a modification - say we no longer want the weight attribute -products.remove( "products", "weight" ); - -# Make the query -results = products.get_products(); -print results -``` - -### Pagination - -The Semantics3 API allows for pagination, so you can request for, say, 5 results, -and then continue to obtain the next 5 from where you stopped previously. For the -python semantics3 module, we have implemented this using iterators. -All you have to do is specify a cache size, and use it the same way you would -any iterator: - -```python -# Specify a cache size -products.cache(5) - -# Iterate through the results -for i in products.iter(): - print i -``` -Our library will automatically request for results 5 products at a time. - - -### Explore Price Histories -For this example, we are going to look at a particular product that is sold by select merchants and has a price of >= USD 30 and seen after a specific date (specified as a UNIX timestamp). - -```python -# Build the query -products.offers_field( "sem3_id", "4znupRCkN6w2Q4Ke4s6sUC"); -products.offers_field( "seller", ["LFleurs","Frys","Walmart"] ); -products.offers_field( "currency", "USD"); -products.offers_field( "price", "gte", 30); -products.offers_field( "lastrecorded_at", "gte", 1348654600); - - - -# Make the query -results = products.get_offers() - -# View the results of the query -print results -``` - - - -## Contributing -Use GitHub's standard fork/commit/pull-request cycle. If you have any questions, email . - -## Author - -* Shawn Tan - -## Copyright - -Copyright (c) 2013 Semantics3 Inc. - -## License - - The "MIT" License - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - diff --git a/README.rst b/README.rst deleted file mode 100644 index e69de29..0000000 diff --git a/setup.py b/setup.py index 5d01468..e8c7bd1 100644 --- a/setup.py +++ b/setup.py @@ -8,10 +8,14 @@ install_requires = [ 'requests-oauthlib >= 0.4.0' ] - - def read(fname): - return open(os.path.join(os.path.dirname(__file__), fname)).read() + try: + import pypandoc + description = pypandoc.convert(fname, 'rst') + except (IOError, ImportError): + description = '' + return description + setup( name="semantics3", version="0.2", @@ -22,7 +26,7 @@ def read(fname): keywords="api ecommerce products", url="https://github.com/Semantics3/semantics3-python", packages=['semantics3'], - long_description=read('README.rst'), + long_description=read('README.md'), install_requires=install_requires, classifiers=[ "Topic :: Utilities", From 8b00a2e817e24a9669ceb2dda760a669e0401845 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Wed, 26 Feb 2014 22:27:31 -0800 Subject: [PATCH 02/48] README rename. --- README | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000..9e81756 --- /dev/null +++ b/README @@ -0,0 +1,198 @@ +# semantics3 +semantics3 is a python client for accessing the Semantics3 Products API, which provides structured information, including pricing histories, for a large number of products. +See https://www.semantics3.com for more information. + +Quickstart guide: https://www.semantics3.com/quickstart +API documentation can be found at https://www.semantics3.com/docs/ + +## Installation +semantics3 can be installed through pypi: + +```bash +pip install semantics3 +``` + +To install the latest source from the repository + +```bash +git clone https://github.com/Semantics3/semantics3-python.git +cd semantics3-python +python setup.py install +``` + +## Requirements +* requests-oauthlib + +## 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 + +### Setup Work + +Let's lay the groundwork. + +```python +from semantics3 import Products + +# Set up a client to talk to the Semantics3 API using your Semantics3 API Credentials +products = Products( + api_key = "SEM3xxxxxxxxxxxxxxxxxxxxxx", + api_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +) +``` + +### First Query aka 'Hello World': + +Let's make our first query! For this query, we are going to search for all Toshiba products that fall under the category of "Computers and Accessories", whose cat_id is 4992. + +```python +# Build the query +products.products_field( "cat_id", 4992 ) +products.products_field( "brand", "Toshiba" ) + +# Make the query +results = products.get_products(); +#or +results = products.get() + +# View the results of the query +print results +``` + +## Examples + +The following examples show you how to interface with some of the core functionality of the Semantics3 Products API. For more detailed examples check out the Quickstart guide: https://www.semantics3.com/quickstart + +### Explore the Category Tree + +In this example we are going to be accessing the categories endpoint. We are going to be specifically exploiring the "Computers and Accessories" category, which has a cat_id of 4992. For more details regarding our category tree and associated cat_ids check out our API docs at https://www.semantics3.com/docs + +```python +# Build the query +products.categories_field( "cat_id", 4992 ); + +# Execute the query +results = products.get_categories(); + +# View the results of the query +print results +``` + +### Nested Search Query + +You can intuitively construct all your complex queries but just repeatedly using the products_field() or add() methods. +Here is how we translate the following JSON query: + +```javascript +{ + "cat_id" : 4992, + "brand" : "Toshiba", + "weight" : { "gte":1000000, "lt":1500000 }, + "sitedetails" : { + "name" : "newegg.com", + "latestoffers" : { + "currency": "USD", + "price" : { "gte" : 100 } + } + } +} +``` + + +This query returns all Toshiba products within a certain weight range narrowed down to just those that retailed recently on newegg.com for >= USD 100. + +```python +# Build the query +products = Products( api_key, api_secret ) +products.products_field( "cat_id", 4992 ) +products.products_field( "brand", "Toshiba" ) +products.products_field( "weight", "gte", 1000000 ) +products.products_field( "weight", "lt", 1500000 ) +products.products_field( "sitedetails", "name", "newegg.com" ) +products.products_field( "sitedetails", "latestoffers", "currency", "USD" ) +products.products_field( "sitedetails", "latestoffers", "price", "gte", 100 ) +# Let's make a modification - say we no longer want the weight attribute +products.remove( "products", "weight" ); + +# Make the query +results = products.get_products(); +print results +``` + +### Pagination + +The Semantics3 API allows for pagination, so you can request for, say, 5 results, +and then continue to obtain the next 5 from where you stopped previously. For the +python semantics3 module, we have implemented this using iterators. +All you have to do is specify a cache size, and use it the same way you would +any iterator: + +```python +# Specify a cache size +products.cache(5) + +# Iterate through the results +for i in products.iter(): + print i +``` +Our library will automatically request for results 5 products at a time. + + +### Explore Price Histories +For this example, we are going to look at a particular product that is sold by select merchants and has a price of >= USD 30 and seen after a specific date (specified as a UNIX timestamp). + +```python +# Build the query +products.offers_field( "sem3_id", "4znupRCkN6w2Q4Ke4s6sUC"); +products.offers_field( "seller", ["LFleurs","Frys","Walmart"] ); +products.offers_field( "currency", "USD"); +products.offers_field( "price", "gte", 30); +products.offers_field( "lastrecorded_at", "gte", 1348654600); + + + +# Make the query +results = products.get_offers() + +# View the results of the query +print results +``` + + + +## Contributing +Use GitHub's standard fork/commit/pull-request cycle. If you have any questions, email . + +## Author + +* Shawn Tan + +## Copyright + +Copyright (c) 2013 Semantics3 Inc. + +## License + + The "MIT" License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + From b3cedb3c1b27ccc3485e5f4de9833a7b320b493d Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Wed, 26 Feb 2014 22:27:31 -0800 Subject: [PATCH 03/48] README rename. --- README | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000..9e81756 --- /dev/null +++ b/README @@ -0,0 +1,198 @@ +# semantics3 +semantics3 is a python client for accessing the Semantics3 Products API, which provides structured information, including pricing histories, for a large number of products. +See https://www.semantics3.com for more information. + +Quickstart guide: https://www.semantics3.com/quickstart +API documentation can be found at https://www.semantics3.com/docs/ + +## Installation +semantics3 can be installed through pypi: + +```bash +pip install semantics3 +``` + +To install the latest source from the repository + +```bash +git clone https://github.com/Semantics3/semantics3-python.git +cd semantics3-python +python setup.py install +``` + +## Requirements +* requests-oauthlib + +## 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 + +### Setup Work + +Let's lay the groundwork. + +```python +from semantics3 import Products + +# Set up a client to talk to the Semantics3 API using your Semantics3 API Credentials +products = Products( + api_key = "SEM3xxxxxxxxxxxxxxxxxxxxxx", + api_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +) +``` + +### First Query aka 'Hello World': + +Let's make our first query! For this query, we are going to search for all Toshiba products that fall under the category of "Computers and Accessories", whose cat_id is 4992. + +```python +# Build the query +products.products_field( "cat_id", 4992 ) +products.products_field( "brand", "Toshiba" ) + +# Make the query +results = products.get_products(); +#or +results = products.get() + +# View the results of the query +print results +``` + +## Examples + +The following examples show you how to interface with some of the core functionality of the Semantics3 Products API. For more detailed examples check out the Quickstart guide: https://www.semantics3.com/quickstart + +### Explore the Category Tree + +In this example we are going to be accessing the categories endpoint. We are going to be specifically exploiring the "Computers and Accessories" category, which has a cat_id of 4992. For more details regarding our category tree and associated cat_ids check out our API docs at https://www.semantics3.com/docs + +```python +# Build the query +products.categories_field( "cat_id", 4992 ); + +# Execute the query +results = products.get_categories(); + +# View the results of the query +print results +``` + +### Nested Search Query + +You can intuitively construct all your complex queries but just repeatedly using the products_field() or add() methods. +Here is how we translate the following JSON query: + +```javascript +{ + "cat_id" : 4992, + "brand" : "Toshiba", + "weight" : { "gte":1000000, "lt":1500000 }, + "sitedetails" : { + "name" : "newegg.com", + "latestoffers" : { + "currency": "USD", + "price" : { "gte" : 100 } + } + } +} +``` + + +This query returns all Toshiba products within a certain weight range narrowed down to just those that retailed recently on newegg.com for >= USD 100. + +```python +# Build the query +products = Products( api_key, api_secret ) +products.products_field( "cat_id", 4992 ) +products.products_field( "brand", "Toshiba" ) +products.products_field( "weight", "gte", 1000000 ) +products.products_field( "weight", "lt", 1500000 ) +products.products_field( "sitedetails", "name", "newegg.com" ) +products.products_field( "sitedetails", "latestoffers", "currency", "USD" ) +products.products_field( "sitedetails", "latestoffers", "price", "gte", 100 ) +# Let's make a modification - say we no longer want the weight attribute +products.remove( "products", "weight" ); + +# Make the query +results = products.get_products(); +print results +``` + +### Pagination + +The Semantics3 API allows for pagination, so you can request for, say, 5 results, +and then continue to obtain the next 5 from where you stopped previously. For the +python semantics3 module, we have implemented this using iterators. +All you have to do is specify a cache size, and use it the same way you would +any iterator: + +```python +# Specify a cache size +products.cache(5) + +# Iterate through the results +for i in products.iter(): + print i +``` +Our library will automatically request for results 5 products at a time. + + +### Explore Price Histories +For this example, we are going to look at a particular product that is sold by select merchants and has a price of >= USD 30 and seen after a specific date (specified as a UNIX timestamp). + +```python +# Build the query +products.offers_field( "sem3_id", "4znupRCkN6w2Q4Ke4s6sUC"); +products.offers_field( "seller", ["LFleurs","Frys","Walmart"] ); +products.offers_field( "currency", "USD"); +products.offers_field( "price", "gte", 30); +products.offers_field( "lastrecorded_at", "gte", 1348654600); + + + +# Make the query +results = products.get_offers() + +# View the results of the query +print results +``` + + + +## Contributing +Use GitHub's standard fork/commit/pull-request cycle. If you have any questions, email . + +## Author + +* Shawn Tan + +## Copyright + +Copyright (c) 2013 Semantics3 Inc. + +## License + + The "MIT" License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + From 7cb6ec0dfe9390aebd9a91f2b77ded23a0587763 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Wed, 26 Feb 2014 22:30:24 -0800 Subject: [PATCH 04/48] Renamed it back. --- README => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README => README.md (100%) diff --git a/README b/README.md similarity index 100% rename from README rename to README.md From 55135efa1635e5bc84c7b861fe5e10afe662569a Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Thu, 27 Feb 2014 09:54:21 -0800 Subject: [PATCH 05/48] Y --- setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.py b/setup.py index e8c7bd1..df75409 100644 --- a/setup.py +++ b/setup.py @@ -14,6 +14,8 @@ def read(fname): description = pypandoc.convert(fname, 'rst') except (IOError, ImportError): description = '' + print(description) + with open('README.rst','w') as f: f.write(description) return description setup( From dcae1bb6c314d338be3f09e2ec7abd4a06c8771f Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Thu, 27 Feb 2014 09:54:29 -0800 Subject: [PATCH 06/48] RST file. --- README.rst | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 README.rst diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..bffac76 --- /dev/null +++ b/README.rst @@ -0,0 +1,234 @@ +semantics3 +========== + +semantics3 is a python client for accessing the Semantics3 Products API, +which provides structured information, including pricing histories, for +a large number of products. See https://www.semantics3.com for more +information. + +Quickstart guide: https://www.semantics3.com/quickstart API +documentation can be found at https://www.semantics3.com/docs/ + +Installation +------------ + +semantics3 can be installed through pypi: + +.. code:: bash + + pip install semantics3 + +To install the latest source from the repository + +.. code:: bash + + git clone https://github.com/Semantics3/semantics3-python.git + cd semantics3-python + python setup.py install + +Requirements +------------ + +- requests-oauthlib + +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 + +Setup Work +~~~~~~~~~~ + +Let's lay the groundwork. + +.. code:: python + + from semantics3 import Products + + # Set up a client to talk to the Semantics3 API using your Semantics3 API Credentials + products = Products( + api_key = "SEM3xxxxxxxxxxxxxxxxxxxxxx", + api_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + ) + +First Query aka 'Hello World': +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Let's make our first query! For this query, we are going to search for +all Toshiba products that fall under the category of "Computers and +Accessories", whose cat\_id is 4992. + +.. code:: python + + # Build the query + products.products_field( "cat_id", 4992 ) + products.products_field( "brand", "Toshiba" ) + + # Make the query + results = products.get_products(); + #or + results = products.get() + + # View the results of the query + print results + +Examples +-------- + +The following examples show you how to interface with some of the core +functionality of the Semantics3 Products API. For more detailed examples +check out the Quickstart guide: https://www.semantics3.com/quickstart + +Explore the Category Tree +~~~~~~~~~~~~~~~~~~~~~~~~~ + +In this example we are going to be accessing the categories endpoint. We +are going to be specifically exploiring the "Computers and Accessories" +category, which has a cat\_id of 4992. For more details regarding our +category tree and associated cat\_ids check out our API docs at +https://www.semantics3.com/docs + +.. code:: python + + # Build the query + products.categories_field( "cat_id", 4992 ); + + # Execute the query + results = products.get_categories(); + + # View the results of the query + print results + +Nested Search Query +~~~~~~~~~~~~~~~~~~~ + +You can intuitively construct all your complex queries but just +repeatedly using the products\_field() or add() methods. Here is how we +translate the following JSON query: + +.. code:: javascript + + { + "cat_id" : 4992, + "brand" : "Toshiba", + "weight" : { "gte":1000000, "lt":1500000 }, + "sitedetails" : { + "name" : "newegg.com", + "latestoffers" : { + "currency": "USD", + "price" : { "gte" : 100 } + } + } + } + +This query returns all Toshiba products within a certain weight range +narrowed down to just those that retailed recently on newegg.com for >= +USD 100. + +.. code:: python + + # Build the query + products = Products( api_key, api_secret ) + products.products_field( "cat_id", 4992 ) + products.products_field( "brand", "Toshiba" ) + products.products_field( "weight", "gte", 1000000 ) + products.products_field( "weight", "lt", 1500000 ) + products.products_field( "sitedetails", "name", "newegg.com" ) + products.products_field( "sitedetails", "latestoffers", "currency", "USD" ) + products.products_field( "sitedetails", "latestoffers", "price", "gte", 100 ) + # Let's make a modification - say we no longer want the weight attribute + products.remove( "products", "weight" ); + + # Make the query + results = products.get_products(); + print results + +Pagination +~~~~~~~~~~ + +The Semantics3 API allows for pagination, so you can request for, say, 5 +results, and then continue to obtain the next 5 from where you stopped +previously. For the python semantics3 module, we have implemented this +using iterators. All you have to do is specify a cache size, and use it +the same way you would any iterator: + +.. code:: python + + # Specify a cache size + products.cache(5) + + # Iterate through the results + for i in products.iter(): + print i + +Our library will automatically request for results 5 products at a time. + +Explore Price Histories +~~~~~~~~~~~~~~~~~~~~~~~ + +For this example, we are going to look at a particular product that is +sold by select merchants and has a price of >= USD 30 and seen after a +specific date (specified as a UNIX timestamp). + +.. code:: python + + # Build the query + products.offers_field( "sem3_id", "4znupRCkN6w2Q4Ke4s6sUC"); + products.offers_field( "seller", ["LFleurs","Frys","Walmart"] ); + products.offers_field( "currency", "USD"); + products.offers_field( "price", "gte", 30); + products.offers_field( "lastrecorded_at", "gte", 1348654600); + + + + # Make the query + results = products.get_offers() + + # View the results of the query + print results + +Contributing +------------ + +Use GitHub's standard fork/commit/pull-request cycle. If you have any +questions, email support@semantics3.com. + +Author +------ + +- Shawn Tan shawn@semantics3.com + +Copyright +--------- + +Copyright (c) 2013 Semantics3 Inc. + +License +------- + +:: + + The "MIT" License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + From c78092c1064f239dfc22900f7b9ff27228ee26a5 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 3 Mar 2014 16:01:42 -0800 Subject: [PATCH 07/48] Cleaned up lines. --- semantics3/semantics3.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index edc07c1..964942c 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -70,8 +70,7 @@ def add(self, endpoint, *fields): else: raise Semantics3Error( 'Invalid constraint', - 'Cannot add this constraint, \'' + parent + '\' is already\ - a value.' + 'Cannot add this constraint, \'' + parent + '\' is already a value.' ) if isinstance(parent, dict): @@ -79,8 +78,7 @@ def add(self, endpoint, *fields): else: raise Semantics3Error( 'Invalid constraint', - 'Cannot add this constraint, \'' + parent + '\' is already\ - a value.' + 'Cannot add this constraint, \'' + parent + '\' is already a value.' ) def field(self, *fields): From 226bb3782a0b5218d75035f2c334ac91ebb602c9 Mon Sep 17 00:00:00 2001 From: Shawn Tan Date: Mon, 3 Mar 2014 16:13:50 -0800 Subject: [PATCH 08/48] Modified to variable request method. Default 'GET' --- semantics3/semantics3.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 964942c..d251353 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -39,10 +39,15 @@ def __init__(self, api_key=None, api_secret=None, endpoint=None): self.query_result = None self.cache_size = 10 - def fetch(self, endpoint, params): + def fetch(self, method, endpoint, params): api_endpoint = API_BASE + endpoint + '?' +\ urllib.urlencode({'q': params}) - content = self.oauth.get(api_endpoint,headers={'User-Agent':'Semantics3 Python Lib/0.2'}) + content = self.oauth.request( + method, + api_endpoint, + headers={'User-Agent':'Semantics3 Python Lib/0.2'} + ) + print(content) return content def remove(self, endpoint, *fields): @@ -101,17 +106,18 @@ def iter(self): if(offset < total_count): self.run_query() - def query(self, endpoint, **kwargs): - content = self.fetch(endpoint, json.dumps(kwargs)).content.decode('utf-8') + def query(self, method, endpoint, **kwargs): + content = self.fetch(method, endpoint, json.dumps(kwargs)).content.decode('utf-8') return json.loads(content) - def run_query(self, endpoint=None): + def run_query(self, endpoint=None, method='GET'): endpoint = endpoint or self.endpoint if not endpoint in self.data_query: - raise Semantics3Error("No query built", "You need to first create\ - a query using the add() method.") + raise Semantics3Error("No query built", + "You need to first createa query using the add() method.") query = self.data_query[endpoint] self.query_result = self.query( + method, endpoint, **query ) From 8d9d0da0dc7b80b92687232ace2e96adc30ec200 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Fri, 9 Jan 2015 16:10:46 +0530 Subject: [PATCH 09/48] Update README.md The README is updated to keep in line/mirror the README.md present in semantics3/semantics3-perl. --- README.md | 154 ++++++++++++++++++++++++------------------------------ 1 file changed, 67 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index 9e81756..cff7365 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,16 @@ semantics3 is a python client for accessing the Semantics3 Products API, which provides structured information, including pricing histories, for a large number of products. See https://www.semantics3.com for more information. -Quickstart guide: https://www.semantics3.com/quickstart API documentation can be found at https://www.semantics3.com/docs/ ## Installation -semantics3 can be installed through pypi: +semantics3 can be installed through pip: ```bash pip install semantics3 ``` -To install the latest source from the repository +To install the latest source: ```bash git clone https://github.com/Semantics3/semantics3-python.git @@ -37,141 +36,122 @@ Let's lay the groundwork. from semantics3 import Products # Set up a client to talk to the Semantics3 API using your Semantics3 API Credentials -products = Products( +sem3 = Products( api_key = "SEM3xxxxxxxxxxxxxxxxxxxxxx", api_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ) ``` -### First Query aka 'Hello World': +### First Request aka 'Hello World': + +Let's run our first request! We are going to run a simple search for the word "iPhone" as follows: -Let's make our first query! For this query, we are going to search for all Toshiba products that fall under the category of "Computers and Accessories", whose cat_id is 4992. ```python -# Build the query -products.products_field( "cat_id", 4992 ) -products.products_field( "brand", "Toshiba" ) +# Build the request +sem3.products_field("search", "iphone") -# Make the query -results = products.get_products(); +# Run the request +results = sem3.get_products() #or -results = products.get() +results = sem3.get() -# View the results of the query +# View the results of the request print results ``` -## Examples +## Sample Requests -The following examples show you how to interface with some of the core functionality of the Semantics3 Products API. For more detailed examples check out the Quickstart guide: https://www.semantics3.com/quickstart +The following examples show you how to interface with some of the core functionality of the Semantics3 Products API. -### Explore the Category Tree +### Pagination -In this example we are going to be accessing the categories endpoint. We are going to be specifically exploiring the "Computers and Accessories" category, which has a cat_id of 4992. For more details regarding our category tree and associated cat_ids check out our API docs at https://www.semantics3.com/docs +The example in our "Hello World" script returns the first 10 results. In this example, we'll scroll to subsequent pages, beyond our initial request: ```python -# Build the query -products.categories_field( "cat_id", 4992 ); +# Build the request +sem3.products_field("search", "iphone") -# Execute the query -results = products.get_categories(); +# Run the request +results = sem3.get_products() -# View the results of the query -print results -``` +# Specify a cache size +sem3.cache(5) -### Nested Search Query - -You can intuitively construct all your complex queries but just repeatedly using the products_field() or add() methods. -Here is how we translate the following JSON query: - -```javascript -{ - "cat_id" : 4992, - "brand" : "Toshiba", - "weight" : { "gte":1000000, "lt":1500000 }, - "sitedetails" : { - "name" : "newegg.com", - "latestoffers" : { - "currency": "USD", - "price" : { "gte" : 100 } - } - } -} +# Iterate through the results +page_no = 0 +for i in sem3.iter(): + page_no += 1 + print "We are at page = %s" % page_no + print "The results for this page are:" + print i + ``` +### UPC Query -This query returns all Toshiba products within a certain weight range narrowed down to just those that retailed recently on newegg.com for >= USD 100. +Running a UPC/EAN/GTIN query is as simple as running a search query: ```python -# Build the query -products = Products( api_key, api_secret ) -products.products_field( "cat_id", 4992 ) -products.products_field( "brand", "Toshiba" ) -products.products_field( "weight", "gte", 1000000 ) -products.products_field( "weight", "lt", 1500000 ) -products.products_field( "sitedetails", "name", "newegg.com" ) -products.products_field( "sitedetails", "latestoffers", "currency", "USD" ) -products.products_field( "sitedetails", "latestoffers", "price", "gte", 100 ) -# Let's make a modification - say we no longer want the weight attribute -products.remove( "products", "weight" ); - -# Make the query -results = products.get_products(); -print results +# Build the request +sem3.products_field("upc", "883974958450") +sem3.products_field("field", ["name","gtins"]) + +# Run the request +results = sem3.get_products() + +# View the results of the request +print results ``` -### Pagination +### URL Query -The Semantics3 API allows for pagination, so you can request for, say, 5 results, -and then continue to obtain the next 5 from where you stopped previously. For the -python semantics3 module, we have implemented this using iterators. -All you have to do is specify a cache size, and use it the same way you would -any iterator: +Get the picture? You can run URL queries as follows: ```python -# Specify a cache size -products.cache(5) - -# Iterate through the results -for i in products.iter(): - print i +sem3.products_field("url", "http://www.walmart.com/ip/15833173") +results = sem3.get_products() +print results ``` -Our library will automatically request for results 5 products at a time. +### Price Filter -### Explore Price Histories -For this example, we are going to look at a particular product that is sold by select merchants and has a price of >= USD 30 and seen after a specific date (specified as a UNIX timestamp). +Filter by price using the "lt" (less than) tag: ```python -# Build the query -products.offers_field( "sem3_id", "4znupRCkN6w2Q4Ke4s6sUC"); -products.offers_field( "seller", ["LFleurs","Frys","Walmart"] ); -products.offers_field( "currency", "USD"); -products.offers_field( "price", "gte", 30); -products.offers_field( "lastrecorded_at", "gte", 1348654600); +sem3.products_field("search", "iphone") +sem3.products_field("price", "lt", 300) +results = sem3.get_products() +print results +``` +### Category ID Query +To lookup details about a cat_id, run your request against the categories resource: -# Make the query -results = products.get_offers() +```python +# Build the request +sem3.categories_field("cat_id", 4992) + +# Run the request +results = sem3.get_categories() -# View the results of the query +# View the results of the request print results ``` - - ## Contributing Use GitHub's standard fork/commit/pull-request cycle. If you have any questions, email . -## Author +## Authors + +* Shawn Tan -* Shawn Tan +* Abishek Bhat ## Copyright -Copyright (c) 2013 Semantics3 Inc. +Copyright (c) 2015 Semantics3 Inc. ## License From 592828e6fa7dadeaf098e074783cb106939542b1 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Sun, 8 Mar 2015 20:50:12 +0100 Subject: [PATCH 10/48] Support for POST Requests. --- semantics3/semantics3.py | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index d251353..6733266 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -40,11 +40,11 @@ def __init__(self, api_key=None, api_secret=None, endpoint=None): self.cache_size = 10 def fetch(self, method, endpoint, params): - api_endpoint = API_BASE + endpoint + '?' +\ - urllib.urlencode({'q': params}) + api_endpoint = API_BASE + endpoint content = self.oauth.request( method, api_endpoint, + params = params, headers={'User-Agent':'Semantics3 Python Lib/0.2'} ) print(content) @@ -107,21 +107,31 @@ def iter(self): self.run_query() def query(self, method, endpoint, **kwargs): - content = self.fetch(method, endpoint, json.dumps(kwargs)).content.decode('utf-8') + if method == "GET": + params = { 'q' : json.dumps(kwargs) } + else: + params = kwargs + content = self.fetch(method, endpoint, params).content.decode('utf-8') return json.loads(content) - def run_query(self, endpoint=None, method='GET'): + def run_query(self, endpoint=None, method='GET', params=None): endpoint = endpoint or self.endpoint - if not endpoint in self.data_query: - raise Semantics3Error("No query built", - "You need to first createa query using the add() method.") - query = self.data_query[endpoint] - self.query_result = self.query( - method, - endpoint, - **query - ) - + if method == "GET" and params == None: + if not endpoint in self.data_query: + raise Semantics3Error("No query built", + "You need to first createa query using the add() method.") + query = self.data_query[endpoint] + self.query_result = self.query( + method, + endpoint, + **query + ) + else: + self.query_result = self.query( + method, + endpoint, + **params + ) if self.query_result['code'] != 'OK': raise Semantics3Error(self.query_result['code'], self.query_result['message']) From 9ad4f7f883f141aefa09400e70dc2331eb59aa77 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Mon, 9 Mar 2015 13:06:33 +0100 Subject: [PATCH 11/48] Support empty GETs and Webhooks Sepcific Changes. --- semantics3/semantics3.py | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 6733266..08a2456 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -106,39 +106,44 @@ def iter(self): if(offset < total_count): self.run_query() - def query(self, method, endpoint, **kwargs): + def query(self, method, endpoint, kwargs): if method == "GET": params = { 'q' : json.dumps(kwargs) } else: params = kwargs - content = self.fetch(method, endpoint, params).content.decode('utf-8') - return json.loads(content) + response = self.fetch(method, endpoint, params) + if response.status_code < 400: + return response.json() + else: + try: + if response.json().get('code') != 'OK': + raise Semantics3Error(self.query_result['code'], + self.query_result['message']) + except: + raise Semantics3Error("400", "Bad Request") def run_query(self, endpoint=None, method='GET', params=None): endpoint = endpoint or self.endpoint - if method == "GET" and params == None: - if not endpoint in self.data_query: - raise Semantics3Error("No query built", - "You need to first createa query using the add() method.") - query = self.data_query[endpoint] + if method == "GET": + try: + query = self.data_query[endpoint] + except KeyError: + query = params or {} self.query_result = self.query( method, endpoint, - **query + query ) else: self.query_result = self.query( method, endpoint, - **params + params ) - if self.query_result['code'] != 'OK': - raise Semantics3Error(self.query_result['code'], - self.query_result['message']) - - def get(self, endpoint=None): - self.run_query(endpoint) return self.query_result + + def get(self, endpoint=None): + return self.run_query(endpoint) def clear_query(self): self.data_query = {} From 2fb773d7c1ae7927ce2e36ece0ee887f20ca3e9e Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Mon, 9 Mar 2015 13:22:20 +0100 Subject: [PATCH 12/48] Add documentation for Webhooks API. --- README.md | 87 ++++++++++++++++++++++++++++++++++++++++ semantics3/semantics3.py | 2 +- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cff7365..f7aac7b 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,93 @@ results = sem3.get_categories() print results ``` +## Webhooks +You can use webhooks to get near-real-time price updates from Semantics3. + +### Creating a webhook + +You can register a webhook with Semantics3 by sending a POST request to `"webhooks"` endpoint. +To verify that your URL is active, a GET request will be sent to your server with a `verification_code` parameter. Your server should respond with `verification_code` in the response body to complete the verification process. + +```python +params = { + webhook_uri : "http://mydomain.com/webhooks-callback-url" +} + +webhook = sem3.run_query("webhooks", params, "POST") +print webhook["id"] +print webhook["webhook_uri"] +``` + +To fetch existing webhooks +```python +webhooks = sem3.run_query("webhooks", "GET") +print webhooks +``` + +To remove a webhook +```python +webhook_id = '7JcGN81u' +endpoint = "webhooks/%s" % webhook_id + +response = sem3.run_query( endpoint, "DELETE") +print response +``` + +### Registering events +Once you register a webhook, you can start adding events to it. Semantics3 server will send you notifications when these events occur. +To register events for a specific webhook send a POST request to the `"webhooks/{webhook_id}/events"` endpoint + +```python +params = { + "type": "price.change", + "product": { + "sem3_id": "1QZC8wchX62eCYS2CACmka" + }, + "constraints": { + "gte": 10, + "lte": 100 + } +} + +webhook_id = '7JcGN81u' +endpoint = "webhooks/" + webhook_id + "/events" + +eventObject = sem3.run_query(endpoint, "POST", params) +print eventObject["id"] +print eventObject["type"] +print eventObject["product"] +``` + +To fetch all registered events for a give webhook +```python +webhook_id = '7JcGN81u' +endpoint = "webhooks/%s/events" % webhook_id + +events = sem3.run_query(endpoint, "GET") +print events +``` + +### Webhook Notifications +Once you have created a webhook and registered events on it, notifications will be sent to your registered webhook URI via a POST request when the corresponding events occur. Make sure that your server can accept POST requests. Here is how a sample notification object looks like +```javascript +{ + "type": "price.change", + "event_id": "XyZgOZ5q", + "notification_id": "X4jsdDsW", + "changes": [{ + "site": "abc.com", + "url": "http://www.abc.com/def", + "previous_price": 45.50, + "current_price": 41.00 + }, { + "site": "walmart.com", + "url": "http://www.walmart.com/ip/20671263", + "previous_price": 34.00, + "current_price": 42.00 + }] +} +``` ## Contributing Use GitHub's standard fork/commit/pull-request cycle. If you have any questions, email . diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 08a2456..81b6262 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -13,7 +13,7 @@ API_DOMAIN = 'api.semantics3.com' -API_BASE = 'https://' + API_DOMAIN + '/v1/' +API_BASE = 'https://' + API_DOMAIN + '/test/v1/' class Semantics3Request: From ab9aff22f582e417dd2cea842b4e6204174cffa1 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Sun, 15 Mar 2015 14:31:31 +0100 Subject: [PATCH 13/48] Update Readme. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f7aac7b..fbc9129 100644 --- a/README.md +++ b/README.md @@ -190,7 +190,7 @@ params = { } webhook_id = '7JcGN81u' -endpoint = "webhooks/" + webhook_id + "/events" +endpoint = "webhooks/%s/events" % webhook_id eventObject = sem3.run_query(endpoint, "POST", params) print eventObject["id"] From 49ac586ec3331d798dd153c84b5c788758fb99cf Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Sun, 15 Mar 2015 14:32:09 +0100 Subject: [PATCH 14/48] Changes for semantics3/sem3-api-webhooks#1. --- semantics3/semantics3.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 81b6262..f6c3832 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -115,12 +115,10 @@ def query(self, method, endpoint, kwargs): if response.status_code < 400: return response.json() else: - try: - if response.json().get('code') != 'OK': - raise Semantics3Error(self.query_result['code'], - self.query_result['message']) - except: - raise Semantics3Error("400", "Bad Request") + if response.json().get('code') != 'OK': + response_body = response.json() + raise Semantics3Error(response_body.get('code'), + response_body.get('message')) def run_query(self, endpoint=None, method='GET', params=None): endpoint = endpoint or self.endpoint From c1872779dfc968bf763563daa0799b3f26a18b34 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Tue, 17 Mar 2015 12:12:20 +0100 Subject: [PATCH 15/48] Use /v1/. --- semantics3/semantics3.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index f6c3832..8542708 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -13,7 +13,7 @@ API_DOMAIN = 'api.semantics3.com' -API_BASE = 'https://' + API_DOMAIN + '/test/v1/' +API_BASE = 'https://' + API_DOMAIN + '/v1/' class Semantics3Request: From fb950c9a6ee75cfa6c979a47418a033da754b8a0 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Tue, 17 Mar 2015 13:22:31 +0100 Subject: [PATCH 16/48] Add API Test Cases. --- setup.py | 2 +- tests/test_product.py | 64 ++++++++++++++++++++++++++++++++++++++++++ tests/test_webhooks.py | 41 +++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 tests/test_product.py create mode 100644 tests/test_webhooks.py diff --git a/setup.py b/setup.py index df75409..9bedda0 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from distutils.core import setup install_requires = [ - 'requests-oauthlib >= 0.4.0' + 'requests-oauthlib >= 0.4.0', ] def read(fname): try: diff --git a/tests/test_product.py b/tests/test_product.py new file mode 100644 index 0000000..8174734 --- /dev/null +++ b/tests/test_product.py @@ -0,0 +1,64 @@ +from semantics3 import Products +import unittest + +sem3 = Products( + api_key = "", + api_secret = "" + ) + + +class TestProductAPI(unittest.TestCase): + + """Docstring for TestProductAPI. """ + def test_get_products(self): + """@todo: Docstring for test_get_products. + :returns: @todo + + """ + sem3.products_field("search", "iphone") + results = sem3.get_products() + self.assertEqual(results['code'], 'OK') + sem3.clear_query() + + def test_upc_query(self): + """@todo: Docstring for test_upc_query. + :returns: @todo + + """ + pass + sem3.products_field("upc", "883974958450") + sem3.products_field("field", ["name","gtins"]) + results = sem3.get_products() + self.assertEqual(results['code'], 'OK') + sem3.clear_query() + + def test_url_query(self): + """@todo: Docstring for test_url_query. + :returns: @todo + + """ + sem3.products_field("url", "http://www.walmart.com/ip/15833173") + results = sem3.get_products() + self.assertEqual(results['code'], 'OK') + sem3.clear_query() + + def test_price_query(self): + """@todo: Docstring for test_price_query. + :returns: @todo + + """ + sem3.products_field("search", "iphone") + sem3.products_field("price", "lt", 300) + results = sem3.get_products() + self.assertEqual(results['code'], 'OK') + sem3.clear_query() + + def test_catid_query(self): + """@todo: Docstring for test_catid_query. + :returns: @todo + + """ + sem3.categories_field("cat_id", 4992) + results = sem3.get_categories() + self.assertEqual(results['code'], 'OK') + sem3.clear_query() diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py new file mode 100644 index 0000000..34e1198 --- /dev/null +++ b/tests/test_webhooks.py @@ -0,0 +1,41 @@ +from semantics3 import Products +import unittest + +sem3 = Products( + api_key = "", + api_secret = "" + ) + + +class TestWebhooksAPI(unittest.TestCase): + + """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) + + def test_get_webhooks(self): + """@todo: Docstring for test_get_webhooks. + :returns: @todo + + """ + webhooks = sem3.run_query('webhooks', "GET") + self.assertEqual(webhooks['status'], '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'] + response = sem3.run_query('webhooks/%s' % webhook_id, "DELETE") + self.assertEqual(response['status'], 'ok') + else: + self.assertEqual(webhooks['status'], 'ok') From 335c16c748d3841c5e458180245b3cb782d8d081 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Tue, 17 Mar 2015 14:56:07 +0100 Subject: [PATCH 17/48] Add api_base to the constructor. --- semantics3/semantics3.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 8542708..9103e14 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -12,13 +12,9 @@ from error import Semantics3Error -API_DOMAIN = 'api.semantics3.com' -API_BASE = 'https://' + API_DOMAIN + '/v1/' - - class Semantics3Request: - def __init__(self, api_key=None, api_secret=None, endpoint=None): + def __init__(self, api_key=None, api_secret=None, endpoint=None, api_base='https://api.semantics3.com/v1/'): if api_key is None: raise Semantics3Error( 'API Credentials Missing', @@ -38,9 +34,10 @@ def __init__(self, api_key=None, api_secret=None, endpoint=None): self.data_query = {} self.query_result = None self.cache_size = 10 + self.api_base = api_base def fetch(self, method, endpoint, params): - api_endpoint = API_BASE + endpoint + api_endpoint = self.api_base + endpoint content = self.oauth.request( method, api_endpoint, From a677430adce88bb7a6d9e4807b3a3e9bf603cc71 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Wed, 25 Mar 2015 12:04:52 +0100 Subject: [PATCH 18/48] Reflect Semantics3Request constructor change --- semantics3/categories.py | 4 ++-- semantics3/offers.py | 4 ++-- semantics3/products.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/semantics3/categories.py b/semantics3/categories.py index 7036647..4835bce 100644 --- a/semantics3/categories.py +++ b/semantics3/categories.py @@ -4,8 +4,8 @@ from semantics3 import Semantics3Request class Categories(Semantics3Request): - def __init__(self, api_key, api_secret): - Semantics3Request.__init__(self, api_key, api_secret, 'categories') + def __init__(self, api_key, api_secret, api_base='https://api.semantics3.com/v1/'): + Semantics3Request.__init__(self, api_key, api_secret, 'categories', api_base) def get_categories(self): return self.get() diff --git a/semantics3/offers.py b/semantics3/offers.py index 2538c02..250c872 100644 --- a/semantics3/offers.py +++ b/semantics3/offers.py @@ -4,8 +4,8 @@ from semantics3 import Semantics3Request class Offers(Semantics3Request): - def __init__(self, api_key, api_secret): - Semantics3Request.__init__(self, api_key, api_secret, 'offers') + def __init__(self, api_key, api_secret, api_base='https://api.semantics3.com/v1/'): + Semantics3Request.__init__(self, api_key, api_secret, 'offers', api_base) def get_offers(self): return self.get() diff --git a/semantics3/products.py b/semantics3/products.py index aa4f3ff..6bc7452 100644 --- a/semantics3/products.py +++ b/semantics3/products.py @@ -5,8 +5,8 @@ class Products(Semantics3Request): - def __init__(self, api_key, api_secret): - Semantics3Request.__init__(self, api_key, api_secret, 'products') + 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 get_products(self): return self.get() From 62feca4cc47fe503bfa5be4f79ceae74657696cb Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Tue, 31 Mar 2015 20:27:06 +0200 Subject: [PATCH 19/48] Install from github --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index fbc9129..72cad19 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,12 @@ semantics3 can be installed through pip: pip install semantics3 ``` +To install the egg directly from github + +```bash +pip install -e git+ssh://git@github.com:Semantics3/semantics3-python.git#egg=semantics3 +``` + To install the latest source: ```bash From 97a925232a564bf7f3b68ad7e6c80f616562b3ab Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Tue, 31 Mar 2015 20:31:22 +0200 Subject: [PATCH 20/48] Fix URL format --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 72cad19..03db3a1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ pip install semantics3 To install the egg directly from github ```bash -pip install -e git+ssh://git@github.com:Semantics3/semantics3-python.git#egg=semantics3 +pip install -e git+ssh://git@github.com/Semantics3/semantics3-python.git#egg=semantics3 ``` To install the latest source: From 92a8f17447a1176d1ff2b681016052fd4c928fd5 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Thu, 2 Apr 2015 10:28:23 +0200 Subject: [PATCH 21/48] Handle when the reposne is not JSON. Fixes #10 --- semantics3/semantics3.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 9103e14..725c997 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -109,6 +109,11 @@ def query(self, method, endpoint, kwargs): else: params = kwargs response = self.fetch(method, endpoint, params) + try: + response_json = response.json() + except: + raise Exception("Malformed JSON") + if response.status_code < 400: return response.json() else: From e00e383e1718bc2096d0fb240880a20c89b653d0 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Thu, 2 Jul 2015 05:34:40 +0000 Subject: [PATCH 22/48] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fbc9129..9130933 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ Running a UPC/EAN/GTIN query is as simple as running a search query: ```python # Build the request sem3.products_field("upc", "883974958450") -sem3.products_field("field", ["name","gtins"]) +sem3.products_field("fields", ["name","gtins"]) # Run the request results = sem3.get_products() From f95e72b334043f138cd7a1558cba4a6d280da050 Mon Sep 17 00:00:00 2001 From: Paul Brown Date: Sat, 1 Aug 2015 22:12:42 -0500 Subject: [PATCH 23/48] Modify pagination example to prevent rate limit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e1061d4..4082a44 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ for i in sem3.iter(): print "We are at page = %s" % page_no print "The results for this page are:" print i - + sleep(1) # prevents rate-limit errors ``` ### UPC Query From f74c18c8fc40f11ea44ec42ccb794ed1879e3998 Mon Sep 17 00:00:00 2001 From: Abishek Bhat Date: Tue, 4 Aug 2015 13:06:09 +0530 Subject: [PATCH 24/48] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4082a44..fcd8d41 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ for i in sem3.iter(): print "We are at page = %s" % page_no print "The results for this page are:" print i - sleep(1) # prevents rate-limit errors + sleep(1) ``` ### UPC Query From 85a1a6d163a5bf3baeb17e1450a2b0c62fde2f6f Mon Sep 17 00:00:00 2001 From: Abishek Bhat Date: Tue, 4 Aug 2015 13:26:20 +0530 Subject: [PATCH 25/48] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fcd8d41..ff8662e 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ for i in sem3.iter(): print "We are at page = %s" % page_no print "The results for this page are:" print i - sleep(1) + sleep(1) #respect rate limit ``` ### UPC Query From 674cf15ea8d87df787dfce36ec466b14fdbd5c0e Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Wed, 9 Sep 2015 09:52:30 +0000 Subject: [PATCH 26/48] Normalize URL. --- semantics3/semantics3.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 725c997..9e52afb 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -1,5 +1,6 @@ import json from requests_oauthlib import OAuth1Session +from urlnorm import norm try: import urllib.parse as urllib @@ -37,7 +38,7 @@ def __init__(self, api_key=None, api_secret=None, endpoint=None, api_base='https self.api_base = api_base def fetch(self, method, endpoint, params): - api_endpoint = self.api_base + endpoint + api_endpoint = norm(self.api_base + endpoint) content = self.oauth.request( method, api_endpoint, From 529fb8acc4e161323f180ca7c614539325ebc92f Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Wed, 9 Sep 2015 09:59:32 +0000 Subject: [PATCH 27/48] Build 0.3.1 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9bedda0..615954d 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ def read(fname): setup( name="semantics3", - version="0.2", + version="0.3.1", author="Shawn Tan", author_email="shawn@semantics3.com", description=("Semantics3 Products API"), From 86e2e33c6fdc564d7459ab1c2332bb3fae158c70 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Wed, 16 Dec 2015 17:17:08 +0000 Subject: [PATCH 28/48] Fixes #13. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 615954d..5532e7e 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,7 @@ install_requires = [ 'requests-oauthlib >= 0.4.0', + 'urlnorm' ] def read(fname): try: From dc0785653d29dd5b641ffc4361f4660ea71d9c7e Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Wed, 16 Dec 2015 17:23:23 +0000 Subject: [PATCH 29/48] Update author name and email. --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 5532e7e..973bee2 100644 --- a/setup.py +++ b/setup.py @@ -22,8 +22,8 @@ def read(fname): setup( name="semantics3", version="0.3.1", - author="Shawn Tan", - author_email="shawn@semantics3.com", + author="Shawn Tan, Abishek Bhat", + author_email="abishek@semantics3.com", description=("Semantics3 Products API"), license="MIT", keywords="api ecommerce products", From d6d78e7dc2f3c6f6a7150fb9db639535c7c4e38b Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Wed, 16 Dec 2015 17:23:47 +0000 Subject: [PATCH 30/48] Bump version to 0.3.2 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 973bee2..ca2864a 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def read(fname): setup( name="semantics3", - version="0.3.1", + version="0.3.2", author="Shawn Tan, Abishek Bhat", author_email="abishek@semantics3.com", description=("Semantics3 Products API"), From 1fd57e55e3bfb31c6264b9069c8b322894229418 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Thu, 28 Jan 2016 04:23:43 +0000 Subject: [PATCH 31/48] Add Python3 disclaimer. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ff8662e..0eaa585 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ See https://www.semantics3.com for more information. API documentation can be found at https://www.semantics3.com/docs/ +_NOTE_ : Semantics3 Python API Library isn't fully compatible with Python3. The library is best used on Python 2.7 + ## Installation semantics3 can be installed through pip: From ea302edf84744ddaeb117c1765f73af20e7fefcc Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Thu, 28 Jan 2016 04:27:58 +0000 Subject: [PATCH 32/48] Bump version to v0.3.3 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ca2864a..ad95c6b 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def read(fname): setup( name="semantics3", - version="0.3.2", + version="0.3.3", author="Shawn Tan, Abishek Bhat", author_email="abishek@semantics3.com", description=("Semantics3 Products API"), From f52bbe1c4e99927896f35d22c259c016cd7e1f69 Mon Sep 17 00:00:00 2001 From: Jake Hickey Date: Mon, 8 Feb 2016 12:07:57 -0500 Subject: [PATCH 33/48] Remove print statement from fetch method --- semantics3/semantics3.py | 1 - 1 file changed, 1 deletion(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 9e52afb..3fc2d09 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -45,7 +45,6 @@ def fetch(self, method, endpoint, params): params = params, headers={'User-Agent':'Semantics3 Python Lib/0.2'} ) - print(content) return content def remove(self, endpoint, *fields): From c9a25c1d59a6ffa3a7390c4e3ba02d810b36ab45 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Wed, 23 Mar 2016 11:37:14 +0000 Subject: [PATCH 34/48] Bump version to 0.3.4. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ad95c6b..0e66fac 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def read(fname): setup( name="semantics3", - version="0.3.3", + version="0.3.4", author="Shawn Tan, Abishek Bhat", author_email="abishek@semantics3.com", description=("Semantics3 Products API"), From ed2fc2ecb45366cca4899caf72f9cf0beb3ed07f Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Mon, 29 Aug 2016 12:38:27 +0000 Subject: [PATCH 35/48] Use python 3 compatible url normalizer. --- semantics3/semantics3.py | 4 ++-- setup.py | 2 +- tests/test_webhooks.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 3fc2d09..af4053c 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -1,6 +1,6 @@ import json from requests_oauthlib import OAuth1Session -from urlnorm import norm +from urltools import normalize try: import urllib.parse as urllib @@ -38,7 +38,7 @@ def __init__(self, api_key=None, api_secret=None, endpoint=None, api_base='https self.api_base = api_base def fetch(self, method, endpoint, params): - api_endpoint = norm(self.api_base + endpoint) + api_endpoint = normalize(self.api_base + endpoint) content = self.oauth.request( method, api_endpoint, diff --git a/setup.py b/setup.py index 0e66fac..204c0fc 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ install_requires = [ 'requests-oauthlib >= 0.4.0', - 'urlnorm' + 'urltools == 0.3.2' ] def read(fname): try: diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py index 34e1198..f39e309 100644 --- a/tests/test_webhooks.py +++ b/tests/test_webhooks.py @@ -16,7 +16,7 @@ def test_webhook_registration(self): :returns: @todo """ - result = sem3.run_query('webhooks', "POST", {"webhook_uri" : "http://148.251.44.168:5000"}) + result = sem3.run_query('webhooks', "POST", {"webhook_uri" : "https://sem3-webhooks-verification.ngrok.io"}) self.assertIn('created', result) def test_get_webhooks(self): From 41d83f73f800ef5a56a76ba12ffe855ee61dbaa1 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Mon, 29 Aug 2016 12:48:25 +0000 Subject: [PATCH 36/48] Fix issue#14 and bump version to 0.3.5 --- README.md | 2 -- setup.py | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 0eaa585..ff8662e 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ See https://www.semantics3.com for more information. API documentation can be found at https://www.semantics3.com/docs/ -_NOTE_ : Semantics3 Python API Library isn't fully compatible with Python3. The library is best used on Python 2.7 - ## Installation semantics3 can be installed through pip: diff --git a/setup.py b/setup.py index 204c0fc..3328bfb 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def read(fname): setup( name="semantics3", - version="0.3.4", + version="0.3.5", author="Shawn Tan, Abishek Bhat", author_email="abishek@semantics3.com", description=("Semantics3 Products API"), From ff8d7dbf7c34a63d04901e3164cb43c2a52357e9 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Fri, 21 Oct 2016 15:33:02 +0000 Subject: [PATCH 37/48] Fix failing post requests. --- semantics3/semantics3.py | 20 ++++++++++++++------ tests/test_product.py | 5 +++-- tests/test_webhooks.py | 40 ++++++++++++++++++++++++++++++++++------ 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index af4053c..44ec541 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -39,12 +39,20 @@ def __init__(self, api_key=None, api_secret=None, endpoint=None, api_base='https def fetch(self, method, endpoint, params): api_endpoint = normalize(self.api_base + endpoint) - content = self.oauth.request( - method, - api_endpoint, - params = params, - headers={'User-Agent':'Semantics3 Python Lib/0.2'} - ) + if method.lower() in ['get', 'delete']: + content = self.oauth.request( + method, + api_endpoint, + params = params, + headers={'User-Agent':'Semantics3 Python Lib/0.2'} + ) + else: + content = self.oauth.request( + method, + api_endpoint, + data = json.dumps(params), + headers={'User-Agent':'Semantics3 Python Lib/0.2', 'Content-Type':'application/json'} + ) return content def remove(self, endpoint, *fields): 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 f39e309..f26ac85 100644 --- a/tests/test_webhooks.py +++ b/tests/test_webhooks.py @@ -1,9 +1,10 @@ -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"] ) @@ -16,7 +17,7 @@ def test_webhook_registration(self): :returns: @todo """ - result = sem3.run_query('webhooks', "POST", {"webhook_uri" : "https://sem3-webhooks-verification.ngrok.io"}) + result = sem3.run_query('webhooks', "POST", {"webhook_uri" : "http://decce40a.ngrok.io"}) self.assertIn('created', result) def test_get_webhooks(self): @@ -26,7 +27,34 @@ def test_get_webhooks(self): """ webhooks = sem3.run_query('webhooks', "GET") self.assertEqual(webhooks['status'], 'ok') - + + def test_register_event(self): + """@todo: Docstring for function. + + :returns: @todo + + """ + webhooks = sem3.run_query('webhooks', "GET") + if len(webhooks['data']): + 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['status'], 'ok') + del params['constraints'] + response1 = sem3.run_query('webhooks/%s/events' % webhook_id, "POST", params) + self.assertEqual(response1['status'], 'ok') + else: + self.assertEqual(webhooks['status'], 'ok') + def test_delete_webhook(self): """@todo: Docstring for test_delete_webhook. :returns: @todo From f9d7597b8dc39921e1c1ce563fd5180cbe36f068 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Fri, 21 Oct 2016 15:38:07 +0000 Subject: [PATCH 38/48] Normalize HTTP method to lower case before checking. --- semantics3/semantics3.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 44ec541..2eded0a 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -112,7 +112,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 @@ -132,7 +132,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: From a50fe209cf04542d50e3d066e917218c21901b6b Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Fri, 21 Oct 2016 15:40:28 +0000 Subject: [PATCH 39/48] Bump version to 0.3.6 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3328bfb..0a3492c 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def read(fname): setup( name="semantics3", - version="0.3.5", + version="0.3.6", author="Shawn Tan, Abishek Bhat", author_email="abishek@semantics3.com", description=("Semantics3 Products API"), From 5dbebd740ccf3fa5222b2efbb1416b5a0a93201a Mon Sep 17 00:00:00 2001 From: Amarnath Ravikumar Date: Fri, 14 Apr 2017 17:46:21 +0530 Subject: [PATCH 40/48] Fixed Dashboard link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ff8662e..0889e5f 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 From 10f1bde9f40ef696e5114b1310e356301b39abe3 Mon Sep 17 00:00:00 2001 From: Amarnath Ravikumar Date: Fri, 14 Apr 2017 17:46:53 +0530 Subject: [PATCH 41/48] Update README.rst --- README.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 ~~~~~~~~~~ From 1ecb3e324aef3747caaebfdb0dc050e33543b51a Mon Sep 17 00:00:00 2001 From: Abishek Bhat Date: Mon, 8 May 2017 17:20:43 +0530 Subject: [PATCH 42/48] Fix webhooks documentation. Closes #20. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0889e5f..54169a1 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,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"] ``` From 07d6d62eac468231b50e6d6da3a0ee9c144cbb39 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Mon, 23 Oct 2017 08:33:53 +0000 Subject: [PATCH 43/48] Fix testcases for new webhooks. --- tests/test_webhooks.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py index f26ac85..b50b123 100644 --- a/tests/test_webhooks.py +++ b/tests/test_webhooks.py @@ -8,25 +8,25 @@ ) -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://decce40a.ngrok.io"}) - 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. @@ -35,7 +35,7 @@ def test_register_event(self): """ webhooks = sem3.run_query('webhooks', "GET") - if len(webhooks['data']): + if len(webhooks['results']): webhook_id = webhooks['data'][0]['id'] params = { "type": "price.change", @@ -48,22 +48,22 @@ def test_register_event(self): } } response = sem3.run_query('webhooks/%s/events' % webhook_id, "POST", params) - self.assertEqual(response['status'], 'ok') + self.assertEqual(response['code'], 'OK') del params['constraints'] response1 = sem3.run_query('webhooks/%s/events' % webhook_id, "POST", params) - self.assertEqual(response1['status'], 'ok') + self.assertEqual(response1['code'], 'OK') else: - self.assertEqual(webhooks['status'], 'ok') - + 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') From ee444b5656af39443dd200ff39d6af5dbe6a0535 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Mon, 23 Oct 2017 08:36:47 +0000 Subject: [PATCH 44/48] Bump version. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 0a3492c..4e66879 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def read(fname): setup( name="semantics3", - version="0.3.6", + version="0.3.7", author="Shawn Tan, Abishek Bhat", author_email="abishek@semantics3.com", description=("Semantics3 Products API"), From 56b8af4a7ed149a601e909bd7bdae814d5b176ec Mon Sep 17 00:00:00 2001 From: Parin Porecha Date: Tue, 19 Sep 2017 13:26:04 +0530 Subject: [PATCH 45/48] Start using url-normalize package instead of urltools for URL normalization --- semantics3/semantics3.py | 8 ++++---- setup.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/semantics3/semantics3.py b/semantics3/semantics3.py index 2eded0a..5b36b48 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -1,6 +1,6 @@ import json from requests_oauthlib import OAuth1Session -from urltools import normalize +from url_normalize import url_normalize try: import urllib.parse as urllib @@ -38,7 +38,7 @@ def __init__(self, api_key=None, api_secret=None, endpoint=None, api_base='https self.api_base = api_base def fetch(self, method, endpoint, params): - api_endpoint = normalize(self.api_base + endpoint) + api_endpoint = url_normalize(self.api_base + endpoint) if method.lower() in ['get', 'delete']: content = self.oauth.request( method, @@ -121,7 +121,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: @@ -149,7 +149,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 4e66879..fb6db06 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ install_requires = [ 'requests-oauthlib >= 0.4.0', - 'urltools == 0.3.2' + 'url-normalize' ] def read(fname): try: From 0072d02007b396d4ff0e7f974dcf7ea42856cd41 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Mon, 23 Oct 2017 08:42:11 +0000 Subject: [PATCH 46/48] Fix #19 and bump version. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index fb6db06..ffde4d3 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def read(fname): setup( name="semantics3", - version="0.3.7", + version="0.3.8", author="Shawn Tan, Abishek Bhat", author_email="abishek@semantics3.com", description=("Semantics3 Products API"), From 5666b48b844ba289b149467d6f872afca9e36c76 Mon Sep 17 00:00:00 2001 From: Amarnath Ravikumar Date: Wed, 8 Aug 2018 21:55:43 +0530 Subject: [PATCH 47/48] added support for setting a client-side timeout value --- README.md | 29 +++++++++++++++++++++++++++-- semantics3/products.py | 4 ++-- semantics3/semantics3.py | 9 ++++++--- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 54169a1..59c424d 100644 --- a/README.md +++ b/README.md @@ -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'] ) ``` @@ -94,6 +94,31 @@ for i in sem3.iter(): 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: 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 5b36b48..c6657e0 100644 --- a/semantics3/semantics3.py +++ b/semantics3/semantics3.py @@ -15,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', @@ -36,6 +36,7 @@ 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 = url_normalize(self.api_base + endpoint) @@ -44,14 +45,16 @@ def fetch(self, method, endpoint, params): method, api_endpoint, params = params, - headers={'User-Agent':'Semantics3 Python Lib/0.2'} + 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'} + headers={'User-Agent':'Semantics3 Python Lib/0.2', 'Content-Type':'application/json'}, + timeout=self.timeout ) return content From 1e48d2910658dc4245393253374c8daa00b86679 Mon Sep 17 00:00:00 2001 From: abishekk92 Date: Mon, 13 Aug 2018 06:18:32 +0000 Subject: [PATCH 48/48] Bump Version. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ffde4d3..da0f211 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ def read(fname): setup( name="semantics3", - version="0.3.8", + version="0.3.9", author="Shawn Tan, Abishek Bhat", author_email="abishek@semantics3.com", description=("Semantics3 Products API"),