From 9d1863ffc7f8d6fd2b9ae503b0e62be1d1e549e5 Mon Sep 17 00:00:00 2001 From: Helen Tran Date: Thu, 19 Jun 2014 14:23:51 -0400 Subject: [PATCH 1/8] First gh-pages commit --- .DS_Store | Bin 0 -> 6148 bytes .travis.yml | 15 - CHANGELOG | 148 ---------- LICENSE | 20 -- MANIFEST.in | 4 - README.md | 4 + RELEASING | 13 - _includes/.DS_Store | Bin 0 -> 6148 bytes _includes/footer.html | 15 + _includes/head.html | 28 ++ _layouts/.DS_Store | Bin 0 -> 6148 bytes _layouts/index.html | 57 ++++ bin/shopify_api.py | 11 - scripts/shopify_api.py | 246 ---------------- setup.py | 40 --- shopify/__init__.py | 3 - shopify/base.py | 151 ---------- shopify/mixins.py | 29 -- shopify/resources/__init__.py | 46 --- shopify/resources/address.py | 5 - shopify/resources/application_charge.py | 7 - shopify/resources/article.py | 26 -- shopify/resources/asset.py | 78 ----- shopify/resources/billing_address.py | 5 - shopify/resources/blog.py | 9 - shopify/resources/carrier_service.py | 5 - shopify/resources/cart.py | 5 - shopify/resources/collect.py | 5 - shopify/resources/comment.py | 19 -- shopify/resources/country.py | 5 - shopify/resources/custom_collection.py | 18 -- shopify/resources/customer.py | 20 -- shopify/resources/customer_group.py | 5 - shopify/resources/customer_saved_search.py | 8 - shopify/resources/event.py | 12 - shopify/resources/fulfillment.py | 11 - shopify/resources/fulfillment_service.py | 5 - shopify/resources/image.py | 18 -- shopify/resources/line_item.py | 6 - shopify/resources/metafield.py | 13 - shopify/resources/note_attribute.py | 5 - shopify/resources/option.py | 5 - shopify/resources/order.py | 21 -- shopify/resources/order_risk.py | 5 - shopify/resources/page.py | 6 - shopify/resources/payment_details.py | 5 - shopify/resources/product.py | 33 --- shopify/resources/product_search_engine.py | 5 - shopify/resources/province.py | 5 - shopify/resources/receipt.py | 5 - .../resources/recurring_application_charge.py | 14 - shopify/resources/redirect.py | 5 - shopify/resources/rule.py | 5 - shopify/resources/script_tag.py | 5 - shopify/resources/shipping_address.py | 5 - shopify/resources/shipping_line.py | 5 - shopify/resources/shop.py | 22 -- shopify/resources/smart_collection.py | 9 - shopify/resources/tax_line.py | 5 - shopify/resources/theme.py | 5 - shopify/resources/transaction.py | 5 - shopify/resources/variant.py | 19 -- shopify/resources/webhook.py | 12 - shopify/session.py | 111 ------- shopify/version.py | 1 - shopify/yamlobjects.py | 18 -- test/__init__.py | 0 test/article_test.py | 65 ----- test/asset_test.py | 41 --- test/base_test.py | 84 ------ test/blog_test.py | 9 - test/carrier_service_test.py | 15 - test/cart_test.py | 13 - test/customer_saved_search_test.py | 23 -- test/fixtures/article.json | 15 - test/fixtures/articles.json | 39 --- test/fixtures/asset.json | 9 - test/fixtures/assets.json | 136 --------- test/fixtures/authors.json | 1 - test/fixtures/blog.json | 13 - test/fixtures/blogs.json | 13 - test/fixtures/carrier_service.json | 9 - test/fixtures/carts.json | 43 --- test/fixtures/customer_saved_search.json | 9 - .../customer_saved_search_customers.json | 60 ---- test/fixtures/events.json | 31 -- test/fixtures/fulfillment.json | 49 ---- test/fixtures/fulfillment_service.json | 10 - test/fixtures/image.json | 10 - test/fixtures/images.json | 20 -- test/fixtures/metafield.json | 12 - test/fixtures/metafields.json | 24 -- test/fixtures/order.json | 275 ------------------ test/fixtures/order_risk.json | 14 - test/fixtures/order_risks.json | 28 -- test/fixtures/product.json | 116 -------- test/fixtures/shop.json | 26 -- test/fixtures/tags.json | 1 - test/fixtures/transaction.json | 29 -- test/fixtures/variant.json | 22 -- test/fixtures/variants.json | 84 ------ test/fulfillment_service_test.py | 15 - test/fulfillment_test.py | 31 -- test/image_test.py | 24 -- test/order_risk_test.py | 42 --- test/order_test.py | 49 ---- test/product_test.py | 42 --- test/recurring_charge_test.py | 9 - test/session_test.py | 158 ---------- test/shop_test.py | 44 --- test/test_helper.py | 56 ---- test/transaction_test.py | 11 - test/variant_test.py | 34 --- 113 files changed, 104 insertions(+), 3215 deletions(-) create mode 100644 .DS_Store delete mode 100644 .travis.yml delete mode 100644 CHANGELOG delete mode 100644 LICENSE delete mode 100644 MANIFEST.in delete mode 100644 RELEASING create mode 100644 _includes/.DS_Store create mode 100644 _includes/footer.html create mode 100644 _includes/head.html create mode 100644 _layouts/.DS_Store create mode 100644 _layouts/index.html delete mode 100755 bin/shopify_api.py delete mode 100755 scripts/shopify_api.py delete mode 100644 setup.py delete mode 100644 shopify/__init__.py delete mode 100644 shopify/base.py delete mode 100644 shopify/mixins.py delete mode 100644 shopify/resources/__init__.py delete mode 100644 shopify/resources/address.py delete mode 100644 shopify/resources/application_charge.py delete mode 100644 shopify/resources/article.py delete mode 100644 shopify/resources/asset.py delete mode 100644 shopify/resources/billing_address.py delete mode 100644 shopify/resources/blog.py delete mode 100644 shopify/resources/carrier_service.py delete mode 100644 shopify/resources/cart.py delete mode 100644 shopify/resources/collect.py delete mode 100644 shopify/resources/comment.py delete mode 100644 shopify/resources/country.py delete mode 100644 shopify/resources/custom_collection.py delete mode 100644 shopify/resources/customer.py delete mode 100644 shopify/resources/customer_group.py delete mode 100644 shopify/resources/customer_saved_search.py delete mode 100644 shopify/resources/event.py delete mode 100644 shopify/resources/fulfillment.py delete mode 100644 shopify/resources/fulfillment_service.py delete mode 100644 shopify/resources/image.py delete mode 100644 shopify/resources/line_item.py delete mode 100644 shopify/resources/metafield.py delete mode 100644 shopify/resources/note_attribute.py delete mode 100644 shopify/resources/option.py delete mode 100644 shopify/resources/order.py delete mode 100644 shopify/resources/order_risk.py delete mode 100644 shopify/resources/page.py delete mode 100644 shopify/resources/payment_details.py delete mode 100644 shopify/resources/product.py delete mode 100644 shopify/resources/product_search_engine.py delete mode 100644 shopify/resources/province.py delete mode 100644 shopify/resources/receipt.py delete mode 100644 shopify/resources/recurring_application_charge.py delete mode 100644 shopify/resources/redirect.py delete mode 100644 shopify/resources/rule.py delete mode 100644 shopify/resources/script_tag.py delete mode 100644 shopify/resources/shipping_address.py delete mode 100644 shopify/resources/shipping_line.py delete mode 100644 shopify/resources/shop.py delete mode 100644 shopify/resources/smart_collection.py delete mode 100644 shopify/resources/tax_line.py delete mode 100644 shopify/resources/theme.py delete mode 100644 shopify/resources/transaction.py delete mode 100644 shopify/resources/variant.py delete mode 100644 shopify/resources/webhook.py delete mode 100644 shopify/session.py delete mode 100644 shopify/version.py delete mode 100644 shopify/yamlobjects.py delete mode 100644 test/__init__.py delete mode 100644 test/article_test.py delete mode 100644 test/asset_test.py delete mode 100644 test/base_test.py delete mode 100644 test/blog_test.py delete mode 100644 test/carrier_service_test.py delete mode 100644 test/cart_test.py delete mode 100644 test/customer_saved_search_test.py delete mode 100644 test/fixtures/article.json delete mode 100644 test/fixtures/articles.json delete mode 100644 test/fixtures/asset.json delete mode 100644 test/fixtures/assets.json delete mode 100644 test/fixtures/authors.json delete mode 100644 test/fixtures/blog.json delete mode 100644 test/fixtures/blogs.json delete mode 100644 test/fixtures/carrier_service.json delete mode 100644 test/fixtures/carts.json delete mode 100644 test/fixtures/customer_saved_search.json delete mode 100644 test/fixtures/customer_saved_search_customers.json delete mode 100644 test/fixtures/events.json delete mode 100644 test/fixtures/fulfillment.json delete mode 100644 test/fixtures/fulfillment_service.json delete mode 100644 test/fixtures/image.json delete mode 100644 test/fixtures/images.json delete mode 100644 test/fixtures/metafield.json delete mode 100644 test/fixtures/metafields.json delete mode 100644 test/fixtures/order.json delete mode 100644 test/fixtures/order_risk.json delete mode 100644 test/fixtures/order_risks.json delete mode 100644 test/fixtures/product.json delete mode 100644 test/fixtures/shop.json delete mode 100644 test/fixtures/tags.json delete mode 100644 test/fixtures/transaction.json delete mode 100644 test/fixtures/variant.json delete mode 100644 test/fixtures/variants.json delete mode 100644 test/fulfillment_service_test.py delete mode 100644 test/fulfillment_test.py delete mode 100644 test/image_test.py delete mode 100644 test/order_risk_test.py delete mode 100644 test/order_test.py delete mode 100644 test/product_test.py delete mode 100644 test/recurring_charge_test.py delete mode 100644 test/session_test.py delete mode 100644 test/shop_test.py delete mode 100644 test/test_helper.py delete mode 100644 test/transaction_test.py delete mode 100644 test/variant_test.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 + +
+
+ Built and maintained by Shopify Inc. © 2014 +
+
+ Want to contribute? Join the team +
+ +
+ + \ No newline at end of file diff --git a/_includes/head.html b/_includes/head.html new file mode 100644 index 00000000..6e4c3274 --- /dev/null +++ b/_includes/head.html @@ -0,0 +1,28 @@ + + + +Shopify Open Source > {{ site.github.project_title }} + +{% if page.description %} + +{% endif %} + + + + + + + + + + + + + + + + diff --git a/_layouts/.DS_Store b/_layouts/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 + + + + + {% include head.html %} + + +
+
+
+
+
+ + Open Source > {{ site.github.project_title }} +
+
+ {{ site.github.language }} +
+
+
+
+
+

{{ site.github.project_title }}

+

{{ site.github.project_tagline }}

+ +
+
+
+ +
+
+ + {{ content }} + +
+
+ {% include footer.html %} + + + + + + diff --git a/bin/shopify_api.py b/bin/shopify_api.py deleted file mode 100755 index 1451af1b..00000000 --- a/bin/shopify_api.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python -"""shopify_api.py wrapper script for running it the source directory""" - -import sys -import os.path - -# Use the development rather than installed version -project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -sys.path.insert(0, project_root) - -execfile(os.path.join(project_root, 'scripts', 'shopify_api.py')) diff --git a/scripts/shopify_api.py b/scripts/shopify_api.py deleted file mode 100755 index bfabe29d..00000000 --- a/scripts/shopify_api.py +++ /dev/null @@ -1,246 +0,0 @@ -#!/usr/bin/env python - -import shopify -import code -import sys -import os -import os.path -import glob -import subprocess -import yaml - -def start_interpreter(**variables): - console = type('shopify ' + shopify.version.VERSION, (code.InteractiveConsole, object), {}) - import readline - console(variables).interact() - -class ConfigFileError(StandardError): - pass - -def usage(usage_string): - """Decorator to add a usage string to a function""" - def decorate(func): - func.usage = usage_string - return func - return decorate - -class TasksMeta(type): - _prog = os.path.basename(sys.argv[0]) - - def __new__(mcs, name, bases, new_attrs): - cls = type.__new__(mcs, name, bases, new_attrs) - - tasks = new_attrs.keys() - tasks.append("help") - def filter_func(item): - return not item.startswith("_") and hasattr(getattr(cls, item), "__call__") - tasks = filter(filter_func, tasks) - cls._tasks = sorted(tasks) - - return cls - - def run_task(cls, task=None, *args): - if task in [None, '-h', '--help']: - cls.help() - return - - # Allow unambigious abbreviations of tasks - if task not in cls._tasks: - matches = filter(lambda item: item.startswith(task), cls._tasks) - if len(matches) == 1: - task = matches[0] - else: - print >>sys.stderr, 'Could not find task "%s".' % (task) - - task_func = getattr(cls, task) - task_func(*args) - - @usage("help [TASK]") - def help(cls, task=None): - """Describe available tasks or one specific task""" - if task is None: - usage_list = [] - for task in iter(cls._tasks): - task_func = getattr(cls, task) - usage_string = " %s %s" % (cls._prog, task_func.usage) - desc = task_func.__doc__.splitlines()[0] - usage_list.append((usage_string, desc)) - max_len = reduce(lambda m, item: max(m, len(item[0])), usage_list, 0) - print("Tasks:") - cols = int(os.environ.get("COLUMNS", 80)) - for line, desc in usage_list: - task_func = getattr(cls, task) - if desc: - line = "%s%s # %s" % (line, " " * (max_len - len(line)), desc) - if len(line) > cols: - line = line[:cols - 3] + "..." - print(line) - else: - task_func = getattr(cls, task) - print("Usage:") - print(" %s %s" % (cls._prog, task_func.usage)) - print("") - print(task_func.__doc__) - - -class Tasks(object): - __metaclass__ = TasksMeta - - _shop_config_dir = os.path.join(os.environ["HOME"], ".shopify", "shops") - _default_symlink = os.path.join(_shop_config_dir, "default") - - @classmethod - @usage("list") - def list(cls): - """list available connections""" - for c in cls._available_connections(): - prefix = " * " if cls._is_default(c) else " " - print(prefix + c) - - @classmethod - @usage("add CONNECTION") - def add(cls, connection): - """create a config file for a connection named CONNECTION""" - filename = cls._get_config_filename(connection) - if os.path.exists(filename): - raise ConfigFileError("There is already a config file at " + filename) - else: - config = dict(protocol='https') - domain = raw_input("Domain? (leave blank for %s.myshopify.com) " % (connection)) - if not domain.strip(): - domain = "%s.myshopify.com" % (connection) - config['domain'] = domain - print("") - print("open https://%s/admin/api in your browser to get API credentials" % (domain)) - config['api_key'] = raw_input("API key? ") - config['password'] = raw_input("Password? ") - if not os.path.isdir(cls._shop_config_dir): - os.makedirs(cls._shop_config_dir) - file(filename, 'w').write(yaml.dump(config, default_flow_style=False, explicit_start="---")) - if len(cls._available_connections()) == 1: - cls.default(connection) - - @classmethod - @usage("remove CONNECTION") - def remove(cls, connection): - """remove the config file for CONNECTION""" - filename = cls._get_config_filename(connection) - if os.path.exists(filename): - if cls._is_default(connection): - os.remove(cls._default_symlink) - os.remove(filename) - else: - cls._no_config_file_error(filename) - - @classmethod - @usage("edit [CONNECTION]") - def edit(cls, connection=None): - """open the config file for CONNECTION with you default editor""" - filename = cls._get_config_filename(connection) - if os.path.exists(filename): - editor = os.environ.get("EDITOR") - if editor: - subprocess.call([editor, filename]) - else: - print("Please set an editor in the EDITOR environment variable") - else: - cls._no_config_file_error(filename) - - @classmethod - @usage("show [CONNECTION]") - def show(cls, connection=None): - """output the location and contents of the CONNECTION's config file""" - if connection is None: - connection = cls._default_connection() - filename = cls._get_config_filename(connection) - if os.path.exists(filename): - print(filename) - print(file(filename).read()) - else: - cls._no_config_file_error(filename) - - @classmethod - @usage("default [CONNECTION]") - def default(cls, connection=None): - """show the default connection, or make CONNECTION the default""" - if connection is not None: - target = cls._get_config_filename(connection) - if os.path.exists(target): - if os.path.exists(cls._default_symlink): - os.remove(cls._default_symlink) - os.symlink(target, cls._default_symlink) - else: - cls._no_config_file_error(target) - if os.path.exists(cls._default_symlink): - print("Default connection is " + cls._default_connection()) - else: - print("There is no default connection set") - - @classmethod - @usage("console [CONNECTION]") - def console(cls, connection=None): - """start an API console for CONNECTION""" - filename = cls._get_config_filename(connection) - if not os.path.exists(filename): - cls._no_config_file_error(filename) - - config = yaml.safe_load(file(filename).read()) - print("using %s" % (config["domain"])) - session = cls._session_from_config(config) - shopify.ShopifyResource.activate_session(session) - - start_interpreter(shopify=shopify) - - @classmethod - @usage("version") - def version(cls, connection=None): - """output the shopify library version""" - print(shopify.version.VERSION) - - @classmethod - def _available_connections(cls): - return map(lambda item: os.path.splitext(os.path.basename(item))[0], - glob.glob(os.path.join(cls._shop_config_dir, "*.yml"))) - - @classmethod - def _default_connection_target(cls): - if not os.path.exists(cls._default_symlink): - return None - target = os.readlink(cls._default_symlink) - return os.path.join(cls._shop_config_dir, target) - - - @classmethod - def _default_connection(cls): - target = cls._default_connection_target() - if not target: - return None - return os.path.splitext(os.path.basename(target))[0] - - @classmethod - def _get_config_filename(cls, connection): - if connection is None: - return cls._default_symlink - else: - return os.path.join(cls._shop_config_dir, connection + ".yml") - - @classmethod - def _session_from_config(cls, config): - session = shopify.Session(config.get("domain")) - session.protocol = config.get("protocol", "https") - session.api_key = config.get("api_key") - session.token = config.get("password") - return session - - @classmethod - def _is_default(cls, connection): - return connection == cls._default_connection() - - @classmethod - def _no_config_file_error(cls, filename): - raise ConfigFileError("There is no config file at " + filename) - -try: - Tasks.run_task(*sys.argv[1:]) -except ConfigFileError, e: - print(e) diff --git a/setup.py b/setup.py deleted file mode 100644 index c24d949b..00000000 --- a/setup.py +++ /dev/null @@ -1,40 +0,0 @@ -from setuptools import setup - -NAME='ShopifyAPI' -execfile('shopify/version.py') -DESCRIPTION='Shopify API for Python' -LONG_DESCRIPTION="""\ -The ShopifyAPI library allows python developers to programmatically -access the admin section of stores using an ActiveResource like -interface similar the ruby Shopify API gem. The library makes HTTP -requests to Shopify in order to list, create, update, or delete -resources (e.g. Order, Product, Collection).""" - -setup(name=NAME, - version=VERSION, - description=DESCRIPTION, - long_description=LONG_DESCRIPTION, - author='Shopify', - author_email='developers@shopify.com', - url='https://github.com/Shopify/shopify_python_api', - packages=['shopify', 'shopify/resources'], - scripts=['scripts/shopify_api.py'], - license='MIT License', - install_requires=[ - 'pyactiveresource>=2.0.0', - 'PyYAML', - ], - test_suite='test', - tests_require=[ - 'mock>=1.0.1', - ], - platforms='Any', - classifiers=['Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Topic :: Software Development', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules'] - ) diff --git a/shopify/__init__.py b/shopify/__init__.py deleted file mode 100644 index 5bad753c..00000000 --- a/shopify/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from shopify.version import VERSION -from shopify.session import Session, ValidationException -from shopify.resources import * diff --git a/shopify/base.py b/shopify/base.py deleted file mode 100644 index d514eace..00000000 --- a/shopify/base.py +++ /dev/null @@ -1,151 +0,0 @@ -import pyactiveresource.connection -from pyactiveresource.activeresource import ActiveResource, ResourceMeta, formats -import shopify.yamlobjects -import shopify.mixins as mixins -import shopify -import threading -import urllib -import urllib2 -import urlparse -import sys - -# Store the response from the last request in the connection object -class ShopifyConnection(pyactiveresource.connection.Connection): - response = None - - def __init__(self, site, user=None, password=None, timeout=None, - format=formats.JSONFormat): - super(ShopifyConnection, self).__init__(site, user, password, timeout, format) - - def _open(self, *args, **kwargs): - self.response = None - try: - self.response = super(ShopifyConnection, self)._open(*args, **kwargs) - except pyactiveresource.connection.ConnectionError, err: - self.response = err.response - raise - return self.response - -# Inherit from pyactiveresource's metaclass in order to use ShopifyConnection -class ShopifyResourceMeta(ResourceMeta): - - @property - def connection(cls): - """HTTP connection for the current thread""" - local = cls._threadlocal - if not getattr(local, 'connection', None): - # Make sure these variables are no longer affected by other threads. - local.user = cls.user - local.password = cls.password - local.site = cls.site - local.timeout = cls.timeout - local.headers = cls.headers - local.format = cls.format - if cls.site is None: - raise ValueError("No shopify session is active") - local.connection = ShopifyConnection( - cls.site, cls.user, cls.password, cls.timeout, cls.format) - return local.connection - - def get_user(cls): - return getattr(cls._threadlocal, 'user', ShopifyResource._user) - - def set_user(cls, value): - cls._threadlocal.connection = None - ShopifyResource._user = cls._threadlocal.user = value - - user = property(get_user, set_user, None, - "The username for HTTP Basic Auth.") - - def get_password(cls): - return getattr(cls._threadlocal, 'password', ShopifyResource._password) - - def set_password(cls, value): - cls._threadlocal.connection = None - ShopifyResource._password = cls._threadlocal.password = value - - password = property(get_password, set_password, None, - "The password for HTTP Basic Auth.") - - def get_site(cls): - return getattr(cls._threadlocal, 'site', ShopifyResource._site) - - def set_site(cls, value): - cls._threadlocal.connection = None - ShopifyResource._site = cls._threadlocal.site = value - if value is not None: - host = urlparse.urlsplit(value)[1] - auth_info, host = urllib2.splituser(host) - if auth_info: - user, password = urllib2.splitpasswd(auth_info) - if user: - cls.user = urllib.unquote(user) - if password: - cls.password = urllib.unquote(password) - - site = property(get_site, set_site, None, - 'The base REST site to connect to.') - - def get_timeout(cls): - return getattr(cls._threadlocal, 'timeout', ShopifyResource._timeout) - - def set_timeout(cls, value): - cls._threadlocal.connection = None - ShopifyResource._timeout = cls._threadlocal.timeout = value - - timeout = property(get_timeout, set_timeout, None, - 'Socket timeout for HTTP requests') - - def get_headers(cls): - if not hasattr(cls._threadlocal, 'headers'): - cls._threadlocal.headers = ShopifyResource._headers.copy() - return cls._threadlocal.headers - - def set_headers(cls, value): - cls._threadlocal.headers = value - - headers = property(get_headers, set_headers, None, - 'The headers sent with HTTP requests') - - def get_format(cls): - return getattr(cls._threadlocal, 'format', ShopifyResource._format) - - def set_format(cls, value): - cls._threadlocal.connection = None - ShopifyResource._format = cls._threadlocal.format = value - - format = property(get_format, set_format, None, - 'Encoding used for request and responses') - - -class ShopifyResource(ActiveResource, mixins.Countable): - __metaclass__ = ShopifyResourceMeta - _format = formats.JSONFormat - _threadlocal = threading.local() - _headers = {'User-Agent': 'ShopifyPythonAPI/%s Python/%s' % (shopify.VERSION, sys.version.split(' ', 1)[0])} - - def __init__(self, attributes=None, prefix_options=None): - if attributes is not None and prefix_options is None: - prefix_options, attributes = self.__class__._split_options(attributes) - return super(ShopifyResource, self).__init__(attributes, prefix_options) - - def is_new(self): - return not self.id - - def _load_attributes_from_response(self, response): - if response.body.strip(): - self._update(self.__class__.format.decode(response.body)) - - @classmethod - def activate_session(cls, session): - cls.site = session.site - cls.user = None - cls.password = None - cls.headers['X-Shopify-Access-Token'] = session.token - - @classmethod - def clear_session(cls): - cls.site = None - cls.user = None - cls.password = None - cls.headers.pop('X-Shopify-Access-Token', None) diff --git a/shopify/mixins.py b/shopify/mixins.py deleted file mode 100644 index 9d3c1796..00000000 --- a/shopify/mixins.py +++ /dev/null @@ -1,29 +0,0 @@ -import shopify.resources - -class Countable(object): - - @classmethod - def count(cls, _options=None, **kwargs): - if _options is None: - _options = kwargs - return int(cls.get("count", **_options)) - - -class Metafields(object): - - def metafields(self): - return shopify.resources.Metafield.find(resource=self.__class__.plural, resource_id=self.id) - - def add_metafield(self, metafield): - if self.is_new(): - raise ValueError("You can only add metafields to a resource that has been saved") - - metafield._prefix_options = dict(resource=self.__class__.plural, resource_id=self.id) - metafield.save() - return metafield - - -class Events(object): - - def events(self): - return shopify.resources.Event.find(resource=self.__class__.plural, resource_id=self.id) diff --git a/shopify/resources/__init__.py b/shopify/resources/__init__.py deleted file mode 100644 index 0884ff89..00000000 --- a/shopify/resources/__init__.py +++ /dev/null @@ -1,46 +0,0 @@ -from shop import Shop -from product import Product -from cart import Cart -from custom_collection import CustomCollection -from collect import Collect -from shipping_address import ShippingAddress -from billing_address import BillingAddress -from line_item import LineItem -from shipping_line import ShippingLine -from note_attribute import NoteAttribute -from address import Address -from option import Option -from payment_details import PaymentDetails -from receipt import Receipt -from rule import Rule -from tax_line import TaxLine -from script_tag import ScriptTag -from product_search_engine import ProductSearchEngine -from application_charge import ApplicationCharge -from recurring_application_charge import RecurringApplicationCharge -from asset import Asset -from theme import Theme -from customer_saved_search import CustomerSavedSearch -from customer_group import CustomerGroup -from customer import Customer -from event import Event -from webhook import Webhook -from redirect import Redirect -from province import Province -from comment import Comment -from metafield import Metafield -from article import Article -from blog import Blog -from page import Page -from country import Country -from fulfillment import Fulfillment -from fulfillment_service import FulfillmentService -from carrier_service import CarrierService -from transaction import Transaction -from image import Image -from variant import Variant -from order import Order -from order_risk import OrderRisk -from smart_collection import SmartCollection - -from ..base import ShopifyResource diff --git a/shopify/resources/address.py b/shopify/resources/address.py deleted file mode 100644 index b5d10718..00000000 --- a/shopify/resources/address.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Address(ShopifyResource): - pass diff --git a/shopify/resources/application_charge.py b/shopify/resources/application_charge.py deleted file mode 100644 index df19e18c..00000000 --- a/shopify/resources/application_charge.py +++ /dev/null @@ -1,7 +0,0 @@ -from ..base import ShopifyResource - - -class ApplicationCharge(ShopifyResource): - - def activate(self): - self._load_attributes_from_response(self.post("activate")) diff --git a/shopify/resources/article.py b/shopify/resources/article.py deleted file mode 100644 index cec30d5a..00000000 --- a/shopify/resources/article.py +++ /dev/null @@ -1,26 +0,0 @@ -from ..base import ShopifyResource -from shopify import mixins -from comment import Comment - - -class Article(ShopifyResource, mixins.Metafields, mixins.Events): - _prefix_source = "/admin/blogs/$blog_id/" - - @classmethod - def _prefix(cls, options={}): - blog_id = options.get("blog_id") - if blog_id: - return "/admin/blogs/%s" % (blog_id) - else: - return "/admin" - - def comments(self): - return Comment.find(article_id=self.id) - - @classmethod - def authors(cls, **kwargs): - return cls.get('authors', **kwargs) - - @classmethod - def tags(cls, **kwargs): - return cls.get('tags', **kwargs) diff --git a/shopify/resources/asset.py b/shopify/resources/asset.py deleted file mode 100644 index 19a7bd76..00000000 --- a/shopify/resources/asset.py +++ /dev/null @@ -1,78 +0,0 @@ -from ..base import ShopifyResource -import base64 - - -class Asset(ShopifyResource): - _primary_key = "key" - _prefix_source = "/admin/themes/$theme_id/" - - @classmethod - def _prefix(cls, options={}): - theme_id = options.get("theme_id") - if theme_id: - return "/admin/themes/%s" % theme_id - else: - return "/admin" - - @classmethod - def _element_path(cls, id, prefix_options={}, query_options=None): - if query_options is None: - prefix_options, query_options = cls._split_options(prefix_options) - return "%s%s.%s%s" % (cls._prefix(prefix_options)+'/', cls.plural, - cls.format.extension, cls._query_string(query_options)) - - @classmethod - def find(cls, key=None, **kwargs): - """ - Find an asset by key - E.g. - shopify.Asset.find('layout/theme.liquid', theme_id=99) - """ - if not key: - return super(Asset, cls).find(**kwargs) - - params = {"asset[key]": key} - params.update(kwargs) - theme_id = params.get("theme_id") - path_prefix = "/admin/themes/%s" % (theme_id) if theme_id else "/admin" - - resource = cls.find_one("%s/assets.%s" % (path_prefix, cls.format.extension), **params) - - if theme_id and resource: - resource._prefix_options["theme_id"] = theme_id - return resource - - def __get_value(self): - data = self.attributes.get("value") - if data: - return data - data = self.attributes.get("attachment") - if data: - return base64.b64decode(data) - - def __set_value(self, data): - self.__wipe_value_attributes() - self.attributes["value"] = data - - value = property(__get_value, __set_value, None, "The asset's value or attachment") - - def attach(self, data): - self.attachment = base64.b64encode(data) - - def destroy(self): - options = {"asset[key]": self.key} - options.update(self._prefix_options) - return self.__class__.connection.delete(self._element_path(self.key, options), self.__class__.headers) - - def is_new(self): - return False - - def __setattr__(self, name, value): - if name in ("value", "attachment", "src", "source_key"): - self.__wipe_value_attributes() - return super(Asset, self).__setattr__(name, value) - - def __wipe_value_attributes(self): - for attr in ("value", "attachment", "src", "source_key"): - if attr in self.attributes: - del self.attributes[attr] diff --git a/shopify/resources/billing_address.py b/shopify/resources/billing_address.py deleted file mode 100644 index 4bf328db..00000000 --- a/shopify/resources/billing_address.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class BillingAddress(ShopifyResource): - pass diff --git a/shopify/resources/blog.py b/shopify/resources/blog.py deleted file mode 100644 index c094560e..00000000 --- a/shopify/resources/blog.py +++ /dev/null @@ -1,9 +0,0 @@ -from ..base import ShopifyResource -from shopify import mixins -from article import Article - - -class Blog(ShopifyResource, mixins.Metafields, mixins.Events): - - def articles(self): - return Article.find(blog_id=self.id) diff --git a/shopify/resources/carrier_service.py b/shopify/resources/carrier_service.py deleted file mode 100644 index 1dfdbb08..00000000 --- a/shopify/resources/carrier_service.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class CarrierService(ShopifyResource): - pass diff --git a/shopify/resources/cart.py b/shopify/resources/cart.py deleted file mode 100644 index da611d52..00000000 --- a/shopify/resources/cart.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Cart(ShopifyResource): - pass diff --git a/shopify/resources/collect.py b/shopify/resources/collect.py deleted file mode 100644 index f40b45ed..00000000 --- a/shopify/resources/collect.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Collect(ShopifyResource): - pass diff --git a/shopify/resources/comment.py b/shopify/resources/comment.py deleted file mode 100644 index 0015eb74..00000000 --- a/shopify/resources/comment.py +++ /dev/null @@ -1,19 +0,0 @@ -from ..base import ShopifyResource - - -class Comment(ShopifyResource): - - def remove(self): - self._load_attributes_from_response(self.post("remove")) - - def spam(self): - self._load_attributes_from_response(self.post("spam")) - - def approve(self): - self._load_attributes_from_response(self.post("approve")) - - def restore(self): - self._load_attributes_from_response(self.post("restore")) - - def not_spam(self): - self._load_attributes_from_response(self.post("not_spam")) diff --git a/shopify/resources/country.py b/shopify/resources/country.py deleted file mode 100644 index 39839808..00000000 --- a/shopify/resources/country.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Country(ShopifyResource): - pass diff --git a/shopify/resources/custom_collection.py b/shopify/resources/custom_collection.py deleted file mode 100644 index fe648bee..00000000 --- a/shopify/resources/custom_collection.py +++ /dev/null @@ -1,18 +0,0 @@ -from ..base import ShopifyResource -from shopify import mixins -from collect import Collect -import product - - -class CustomCollection(ShopifyResource, mixins.Metafields, mixins.Events): - - def products(self): - return product.Product.find(collection_id=self.id) - - def add_product(self, product): - return Collect.create({'collection_id': self.id, 'product_id': product.id}) - - def remove_product(self, product): - collect = Collect.find_first(collection_id=self.id, product_id=product.id) - if collect: - collect.destroy() diff --git a/shopify/resources/customer.py b/shopify/resources/customer.py deleted file mode 100644 index 2855962a..00000000 --- a/shopify/resources/customer.py +++ /dev/null @@ -1,20 +0,0 @@ -from ..base import ShopifyResource -from shopify import mixins - - -class Customer(ShopifyResource, mixins.Metafields): - - @classmethod - def search(cls, **kwargs): - """ - Search for customers matching supplied query - - Args: - q: Text to search for customers ("q" is short for query) - f: Filters to apply to customers ("f" is short for query) - page: Page to show (default: 1) - limit: Maximum number of results to show (default: 50, maximum: 250) - Returns: - An array of customers. - """ - return cls._build_list(cls.get("search", **kwargs)) diff --git a/shopify/resources/customer_group.py b/shopify/resources/customer_group.py deleted file mode 100644 index 900c0b4a..00000000 --- a/shopify/resources/customer_group.py +++ /dev/null @@ -1,5 +0,0 @@ -from customer_saved_search import CustomerSavedSearch - - -class CustomerGroup(CustomerSavedSearch): - pass diff --git a/shopify/resources/customer_saved_search.py b/shopify/resources/customer_saved_search.py deleted file mode 100644 index a19dae48..00000000 --- a/shopify/resources/customer_saved_search.py +++ /dev/null @@ -1,8 +0,0 @@ -from ..base import ShopifyResource -from customer import Customer - - -class CustomerSavedSearch(ShopifyResource): - - def customers(cls, **kwargs): - return Customer._build_list(cls.get("customers", **kwargs)) diff --git a/shopify/resources/event.py b/shopify/resources/event.py deleted file mode 100644 index 8b25ce38..00000000 --- a/shopify/resources/event.py +++ /dev/null @@ -1,12 +0,0 @@ -from ..base import ShopifyResource - -class Event(ShopifyResource): - _prefix_source = "/admin/$resource/$resource_id/" - - @classmethod - def _prefix(cls, options={}): - resource = options.get("resource") - if resource: - return "/admin/%s/%s" % (resource, options["resource_id"]) - else: - return "/admin" diff --git a/shopify/resources/fulfillment.py b/shopify/resources/fulfillment.py deleted file mode 100644 index 10096a8e..00000000 --- a/shopify/resources/fulfillment.py +++ /dev/null @@ -1,11 +0,0 @@ -from ..base import ShopifyResource - - -class Fulfillment(ShopifyResource): - _prefix_source = "/admin/orders/$order_id/" - - def cancel(self): - self._load_attributes_from_response(self.post("cancel")) - - def complete(self): - self._load_attributes_from_response(self.post("complete")) diff --git a/shopify/resources/fulfillment_service.py b/shopify/resources/fulfillment_service.py deleted file mode 100644 index f303fe38..00000000 --- a/shopify/resources/fulfillment_service.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class FulfillmentService(ShopifyResource): - pass diff --git a/shopify/resources/image.py b/shopify/resources/image.py deleted file mode 100644 index 755c09e7..00000000 --- a/shopify/resources/image.py +++ /dev/null @@ -1,18 +0,0 @@ -from ..base import ShopifyResource -import base64 -import re - - -class Image(ShopifyResource): - _prefix_source = "/admin/products/$product_id/" - - def __getattr__(self, name): - if name in ["pico", "icon", "thumb", "small", "compact", "medium", "large", "grande", "original"]: - return re.sub(r"/(.*)\.(\w{2,4})", r"/\1_%s.\2" % (name), self.src) - else: - return super(Image, self).__getattr__(name) - - def attach_image(self, data, filename=None): - self.attributes["attachment"] = base64.b64encode(data) - if filename: - self.attributes["filename"] = filename diff --git a/shopify/resources/line_item.py b/shopify/resources/line_item.py deleted file mode 100644 index cac2ceed..00000000 --- a/shopify/resources/line_item.py +++ /dev/null @@ -1,6 +0,0 @@ -from ..base import ShopifyResource - - -class LineItem(ShopifyResource): - class Property(ShopifyResource): - pass diff --git a/shopify/resources/metafield.py b/shopify/resources/metafield.py deleted file mode 100644 index f37af161..00000000 --- a/shopify/resources/metafield.py +++ /dev/null @@ -1,13 +0,0 @@ -from ..base import ShopifyResource - - -class Metafield(ShopifyResource): - _prefix_source = "/admin/$resource/$resource_id/" - - @classmethod - def _prefix(cls, options={}): - resource = options.get("resource") - if resource: - return "/admin/%s/%s" % (resource, options["resource_id"]) - else: - return "/admin" diff --git a/shopify/resources/note_attribute.py b/shopify/resources/note_attribute.py deleted file mode 100644 index 9e997e5e..00000000 --- a/shopify/resources/note_attribute.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class NoteAttribute(ShopifyResource): - pass diff --git a/shopify/resources/option.py b/shopify/resources/option.py deleted file mode 100644 index 3ff640d5..00000000 --- a/shopify/resources/option.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Option(ShopifyResource): - pass diff --git a/shopify/resources/order.py b/shopify/resources/order.py deleted file mode 100644 index c902a5d0..00000000 --- a/shopify/resources/order.py +++ /dev/null @@ -1,21 +0,0 @@ -from ..base import ShopifyResource -from shopify import mixins -from transaction import Transaction - - -class Order(ShopifyResource, mixins.Metafields, mixins.Events): - - def close(self): - self._load_attributes_from_response(self.post("close")) - - def open(self): - self._load_attributes_from_response(self.post("open")) - - def cancel(self, **kwargs): - self._load_attributes_from_response(self.post("cancel", **kwargs)) - - def transactions(self): - return Transaction.find(order_id=self.id) - - def capture(self, amount=""): - return Transaction.create({"amount": amount, "kind": "capture", "order_id": self.id}) diff --git a/shopify/resources/order_risk.py b/shopify/resources/order_risk.py deleted file mode 100644 index 2cc4c268..00000000 --- a/shopify/resources/order_risk.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - -class OrderRisk(ShopifyResource): - _prefix_source = "/admin/orders/$order_id/" - _plural = "risks" diff --git a/shopify/resources/page.py b/shopify/resources/page.py deleted file mode 100644 index aa2711b2..00000000 --- a/shopify/resources/page.py +++ /dev/null @@ -1,6 +0,0 @@ -from ..base import ShopifyResource -from shopify import mixins - - -class Page(ShopifyResource, mixins.Metafields, mixins.Events): - pass diff --git a/shopify/resources/payment_details.py b/shopify/resources/payment_details.py deleted file mode 100644 index 24bed6d0..00000000 --- a/shopify/resources/payment_details.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class PaymentDetails(ShopifyResource): - pass diff --git a/shopify/resources/product.py b/shopify/resources/product.py deleted file mode 100644 index f824e252..00000000 --- a/shopify/resources/product.py +++ /dev/null @@ -1,33 +0,0 @@ -from ..base import ShopifyResource -from shopify import mixins -from custom_collection import CustomCollection -from smart_collection import SmartCollection - - -class Product(ShopifyResource, mixins.Metafields, mixins.Events): - - def price_range(self): - prices = [float(variant.price) for variant in self.variants] - f = "%0.2f" - min_price = min(prices) - max_price = max(prices) - if min_price != max_price: - return "%s - %s" % (f % min_price, f % max_price) - else: - return f % min_price - - def collections(self): - return CustomCollection.find(product_id=self.id) - - def smart_collections(self): - return SmartCollection.find(product_id=self.id) - - def add_to_collection(self, collection): - return collection.add_product(self) - - def remove_from_collection(self, collection): - return collection.remove_product(self) - - def add_variant(self, variant): - variant.attributes['product_id'] = self.id - return variant.save() diff --git a/shopify/resources/product_search_engine.py b/shopify/resources/product_search_engine.py deleted file mode 100644 index 44976245..00000000 --- a/shopify/resources/product_search_engine.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class ProductSearchEngine(ShopifyResource): - pass diff --git a/shopify/resources/province.py b/shopify/resources/province.py deleted file mode 100644 index d34496f9..00000000 --- a/shopify/resources/province.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Province(ShopifyResource): - _prefix_source = "/admin/countries/$country_id/" diff --git a/shopify/resources/receipt.py b/shopify/resources/receipt.py deleted file mode 100644 index 0dd86a39..00000000 --- a/shopify/resources/receipt.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Receipt(ShopifyResource): - pass diff --git a/shopify/resources/recurring_application_charge.py b/shopify/resources/recurring_application_charge.py deleted file mode 100644 index f0e30045..00000000 --- a/shopify/resources/recurring_application_charge.py +++ /dev/null @@ -1,14 +0,0 @@ -from ..base import ShopifyResource - - -class RecurringApplicationCharge(ShopifyResource): - - @classmethod - def current(cls): - return cls.find_first(status="active") - - def cancel(self): - self._load_attributes_from_response(self.destroy) - - def activate(self): - self._load_attributes_from_response(self.post("activate")) diff --git a/shopify/resources/redirect.py b/shopify/resources/redirect.py deleted file mode 100644 index 041ecb81..00000000 --- a/shopify/resources/redirect.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Redirect(ShopifyResource): - pass diff --git a/shopify/resources/rule.py b/shopify/resources/rule.py deleted file mode 100644 index 27c460c3..00000000 --- a/shopify/resources/rule.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Rule(ShopifyResource): - pass diff --git a/shopify/resources/script_tag.py b/shopify/resources/script_tag.py deleted file mode 100644 index b627778c..00000000 --- a/shopify/resources/script_tag.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class ScriptTag(ShopifyResource): - pass diff --git a/shopify/resources/shipping_address.py b/shopify/resources/shipping_address.py deleted file mode 100644 index 283aff34..00000000 --- a/shopify/resources/shipping_address.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class ShippingAddress(ShopifyResource): - pass diff --git a/shopify/resources/shipping_line.py b/shopify/resources/shipping_line.py deleted file mode 100644 index 1f0d4c2b..00000000 --- a/shopify/resources/shipping_line.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class ShippingLine(ShopifyResource): - pass diff --git a/shopify/resources/shop.py b/shopify/resources/shop.py deleted file mode 100644 index e179eef4..00000000 --- a/shopify/resources/shop.py +++ /dev/null @@ -1,22 +0,0 @@ -from ..base import ShopifyResource -from metafield import Metafield -from event import Event - - -class Shop(ShopifyResource): - - @classmethod - def current(cls): - return cls.find_one("/admin/shop." + cls.format.extension) - - def metafields(self): - return Metafield.find() - - def add_metafield(self, metafield): - if self.is_new(): - raise ValueError("You can only add metafields to a resource that has been saved") - metafield.save() - return metafield - - def events(self): - return Event.find() diff --git a/shopify/resources/smart_collection.py b/shopify/resources/smart_collection.py deleted file mode 100644 index 1ff4e607..00000000 --- a/shopify/resources/smart_collection.py +++ /dev/null @@ -1,9 +0,0 @@ -from ..base import ShopifyResource -from shopify import mixins -import product - - -class SmartCollection(ShopifyResource, mixins.Metafields, mixins.Events): - - def products(self): - return product.Product.find(collection_id=self.id) diff --git a/shopify/resources/tax_line.py b/shopify/resources/tax_line.py deleted file mode 100644 index b9cda0c7..00000000 --- a/shopify/resources/tax_line.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class TaxLine(ShopifyResource): - pass diff --git a/shopify/resources/theme.py b/shopify/resources/theme.py deleted file mode 100644 index d0ea8655..00000000 --- a/shopify/resources/theme.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Theme(ShopifyResource): - pass diff --git a/shopify/resources/transaction.py b/shopify/resources/transaction.py deleted file mode 100644 index aaed92b9..00000000 --- a/shopify/resources/transaction.py +++ /dev/null @@ -1,5 +0,0 @@ -from ..base import ShopifyResource - - -class Transaction(ShopifyResource): - _prefix_source = "/admin/orders/$order_id/" diff --git a/shopify/resources/variant.py b/shopify/resources/variant.py deleted file mode 100644 index cc4f5485..00000000 --- a/shopify/resources/variant.py +++ /dev/null @@ -1,19 +0,0 @@ -from ..base import ShopifyResource -from shopify import mixins - - -class Variant(ShopifyResource, mixins.Metafields): - _prefix_source = "/admin/products/$product_id/" - - @classmethod - def _prefix(cls, options={}): - product_id = options.get("product_id") - if product_id: - return "/admin/products/%s" % (product_id) - else: - return "/admin" - - def save(self): - if 'product_id' not in self._prefix_options: - self._prefix_options['product_id'] = self.product_id - return super(ShopifyResource, self).save() diff --git a/shopify/resources/webhook.py b/shopify/resources/webhook.py deleted file mode 100644 index 452934f3..00000000 --- a/shopify/resources/webhook.py +++ /dev/null @@ -1,12 +0,0 @@ -from ..base import ShopifyResource - - -class Webhook(ShopifyResource): - - def __get_format(self): - return self.attributes.get("format") - - def __set_format(self, data): - self.attributes["format"] = data - - format = property(__get_format, __set_format, None, "Format attribute") diff --git a/shopify/session.py b/shopify/session.py deleted file mode 100644 index 14c1cbac..00000000 --- a/shopify/session.py +++ /dev/null @@ -1,111 +0,0 @@ -import time -import urllib -import urllib2 -try: - from hashlib import md5 -except ImportError: - from md5 import md5 -try: - import simplejson as json -except ImportError: - import json -import re -from contextlib import contextmanager - -class ValidationException(Exception): - pass - -class Session(object): - api_key = None - secret = None - protocol = 'https' - - @classmethod - def setup(cls, **kwargs): - for k, v in kwargs.iteritems(): - setattr(cls, k, v) - - @classmethod - @contextmanager - def temp(cls, domain, token): - import shopify - original_domain = shopify.ShopifyResource.get_site() - original_token = shopify.ShopifyResource.get_headers().get('X-Shopify-Access-Token') - original_session = shopify.Session(original_domain, original_token) - - session = Session(domain, token) - shopify.ShopifyResource.activate_session(session) - yield - shopify.ShopifyResource.activate_session(original_session) - - def __init__(self, shop_url, token=None, params=None): - self.url = self.__prepare_url(shop_url) - self.token = token - return - - def create_permission_url(self, scope, redirect_uri=None): - query_params = dict(client_id=self.api_key, scope=",".join(scope)) - if redirect_uri: query_params['redirect_uri'] = redirect_uri - return "%s://%s/admin/oauth/authorize?%s" % (self.protocol, self.url, urllib.urlencode(query_params)) - - def request_token(self, params): - if self.token: - return self.token - - if not self.validate_params(params): - raise ValidationException('Invalid Signature: Possibly malicious login') - - code = params['code'] - - url = "%s://%s/admin/oauth/access_token?" % (self.protocol, self.url) - query_params = dict(client_id=self.api_key, client_secret=self.secret, code=code) - request = urllib2.Request(url, urllib.urlencode(query_params)) - response = urllib2.urlopen(request) - - if response.code == 200: - self.token = json.loads(response.read())['access_token'] - return self.token - else: - raise Exception(response.msg) - - @property - def site(self): - return "%s://%s/admin" % (self.protocol, self.url) - - @property - def valid(self): - return self.url is not None and self.token is not None - - @staticmethod - def __prepare_url(url): - if not url or (url.strip() == ""): - return None - url = re.sub("https?://", "", url) - url = re.sub("/.*", "", url) - if url.find(".") == -1: - url += ".myshopify.com" - return url - - @classmethod - def validate_params(cls, params): - # Avoid replay attacks by making sure the request - # isn't more than a day old. - one_day = 24 * 60 * 60 - if int(params['timestamp']) < time.time() - one_day: - return False - - return cls.validate_signature(params) - - @classmethod - def validate_signature(cls, params): - if "signature" not in params: - return False - - sorted_params = "" - signature = params['signature'] - - for k in sorted(params.keys()): - if k != "signature": - sorted_params += k + "=" + str(params[k]) - - return md5(cls.secret + sorted_params).hexdigest() == signature diff --git a/shopify/version.py b/shopify/version.py deleted file mode 100644 index f80f88dc..00000000 --- a/shopify/version.py +++ /dev/null @@ -1 +0,0 @@ -VERSION = '2.0.4' diff --git a/shopify/yamlobjects.py b/shopify/yamlobjects.py deleted file mode 100644 index d4e7cd3a..00000000 --- a/shopify/yamlobjects.py +++ /dev/null @@ -1,18 +0,0 @@ -try: - # Shopify serializes receipts in YAML format, and yaml.safe_load will - # not automatically load custom types because of security purpose, - # so create safe loaders for types returned from Shopify here. - # - # The YAMLObject metaclass will automatically add these classes to - # the list of constructors for yaml.safe_load to use. - import yaml - - class YAMLHashWithIndifferentAccess(yaml.YAMLObject): - yaml_tag = '!map:ActiveSupport::HashWithIndifferentAccess' - yaml_loader = yaml.SafeLoader - - @classmethod - def from_yaml(cls, loader, node): - return loader.construct_mapping(node, cls) -except ImportError: - pass diff --git a/test/__init__.py b/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/article_test.py b/test/article_test.py deleted file mode 100644 index e8f6f234..00000000 --- a/test/article_test.py +++ /dev/null @@ -1,65 +0,0 @@ -import shopify -from test_helper import TestCase - -class ArticleTest(TestCase): - - def test_create_article(self): - self.fake("blogs/1008414260/articles", method='POST', body=self.load_fixture('article'), headers={'Content-type': 'application/json'}) - article = shopify.Article({'blog_id':1008414260}) - article.save() - self.assertEqual("First Post", article.title) - - def test_get_article(self): - self.fake('articles/6242736', method='GET', body=self.load_fixture('article')) - article = shopify.Article.find(6242736) - self.assertEqual("First Post", article.title) - - def test_update_article(self): - self.fake('articles/6242736', method='GET', body=self.load_fixture('article')) - article = shopify.Article.find(6242736) - - self.fake('articles/6242736', method='PUT', body=self.load_fixture('article'), headers={'Content-type': 'application/json'}) - article.save() - - def test_get_articles(self): - self.fake("articles", method='GET', body=self.load_fixture('articles')) - articles = shopify.Article.find() - self.assertEqual(3, len(articles)) - - def test_get_articles_namespaced(self): - self.fake("blogs/1008414260/articles", method='GET', body=self.load_fixture('articles')) - articles = shopify.Article.find(blog_id=1008414260) - self.assertEqual(3, len(articles)) - - def test_get_article_namespaced(self): - self.fake("blogs/1008414260/articles/6242736", method='GET', body=self.load_fixture('article')) - article = shopify.Article.find(6242736, blog_id=1008414260) - self.assertEqual("First Post", article.title) - - def test_get_authors(self): - self.fake("articles/authors", method='GET', body=self.load_fixture('authors')) - authors = shopify.Article.authors() - self.assertEqual("Shopify", authors[0]) - self.assertEqual("development shop", authors[-1]) - - def test_get_authors_for_blog_id(self): - self.fake("blogs/1008414260/articles/authors", method='GET', body=self.load_fixture('authors')) - authors = shopify.Article.authors(blog_id=1008414260) - self.assertEqual(3, len(authors)) - - def test_get_tags(self): - self.fake("articles/tags", method='GET', body=self.load_fixture('tags')) - tags = shopify.Article.tags() - self.assertEqual("consequuntur", tags[0]) - self.assertEqual("repellendus", tags[-1]) - - def test_get_tags_for_blog_id(self): - self.fake("blogs/1008414260/articles/tags", method='GET', body=self.load_fixture('tags')) - tags = shopify.Article.tags(blog_id=1008414260) - self.assertEqual("consequuntur", tags[0]) - self.assertEqual("repellendus", tags[-1]) - - def test_get_popular_tags(self): - self.fake("articles/tags.json?limit=1&popular=1", extension=False, method='GET', body=self.load_fixture('tags')) - tags = shopify.Article.tags(popular=1, limit=1) - self.assertEqual(3, len(tags)) diff --git a/test/asset_test.py b/test/asset_test.py deleted file mode 100644 index 00ce1396..00000000 --- a/test/asset_test.py +++ /dev/null @@ -1,41 +0,0 @@ -import shopify -from test_helper import TestCase - -class AssetTest(TestCase): - - def test_get_assets(self): - self.fake("assets", method='GET', body=self.load_fixture('assets')) - v = shopify.Asset.find() - - def test_get_asset(self): - self.fake("assets.json?asset%5Bkey%5D=templates%2Findex.liquid", extension=False, method='GET', body=self.load_fixture('asset')) - v = shopify.Asset.find('templates/index.liquid') - - def test_update_asset(self): - self.fake("assets.json?asset%5Bkey%5D=templates%2Findex.liquid", extension=False, method='GET', body=self.load_fixture('asset')) - v = shopify.Asset.find('templates/index.liquid') - - self.fake("assets", method='PUT', body=self.load_fixture('asset'), headers={'Content-type': 'application/json'}) - v.save() - - def test_get_assets_namespaced(self): - self.fake("themes/1/assets", method='GET', body=self.load_fixture('assets')) - v = shopify.Asset.find(theme_id = 1) - - def test_get_asset_namespaced(self): - self.fake("themes/1/assets.json?asset%5Bkey%5D=templates%2Findex.liquid&theme_id=1", extension=False, method='GET', body=self.load_fixture('asset')) - v = shopify.Asset.find('templates/index.liquid', theme_id=1) - - def test_update_asset_namespaced(self): - self.fake("themes/1/assets.json?asset%5Bkey%5D=templates%2Findex.liquid&theme_id=1", extension=False, method='GET', body=self.load_fixture('asset')) - v = shopify.Asset.find('templates/index.liquid', theme_id=1) - - self.fake("themes/1/assets", method='PUT', body=self.load_fixture('asset'), headers={'Content-type': 'application/json'}) - v.save() - - def test_delete_asset_namespaced(self): - self.fake("themes/1/assets.json?asset%5Bkey%5D=templates%2Findex.liquid&theme_id=1", extension=False, method='GET', body=self.load_fixture('asset')) - v = shopify.Asset.find('templates/index.liquid', theme_id=1) - - self.fake("themes/1/assets.json?asset%5Bkey%5D=templates%2Findex.liquid", extension=False, method='DELETE', body="{}") - v.destroy() diff --git a/test/base_test.py b/test/base_test.py deleted file mode 100644 index 9e022a94..00000000 --- a/test/base_test.py +++ /dev/null @@ -1,84 +0,0 @@ -import shopify -from test_helper import TestCase -from pyactiveresource.activeresource import ActiveResource -from mock import patch -import threading - -class BaseTest(TestCase): - - @classmethod - def setUpClass(self): - self.session1 = shopify.Session('shop1.myshopify.com', 'token1') - self.session2 = shopify.Session('shop2.myshopify.com', 'token2') - - def setUp(self): - super(BaseTest, self).setUp() - - def tearDown(self): - shopify.ShopifyResource.clear_session() - - def test_activate_session_should_set_site_and_headers_for_given_session(self): - shopify.ShopifyResource.activate_session(self.session1) - - self.assertIsNone(ActiveResource.site) - self.assertEqual('https://shop1.myshopify.com/admin', shopify.ShopifyResource.site) - self.assertEqual('https://shop1.myshopify.com/admin', shopify.Shop.site) - self.assertIsNone(ActiveResource.headers) - self.assertEqual('token1', shopify.ShopifyResource.headers['X-Shopify-Access-Token']) - self.assertEqual('token1', shopify.Shop.headers['X-Shopify-Access-Token']) - - def test_clear_session_should_clear_site_and_headers_from_Base(self): - shopify.ShopifyResource.activate_session(self.session1) - shopify.ShopifyResource.clear_session() - - self.assertIsNone(ActiveResource.site) - self.assertIsNone(shopify.ShopifyResource.site) - self.assertIsNone(shopify.Shop.site) - - self.assertIsNone(ActiveResource.headers) - self.assertFalse('X-Shopify-Access-Token' in shopify.ShopifyResource.headers) - self.assertFalse('X-Shopify-Access-Token' in shopify.Shop.headers) - - def test_activate_session_with_one_session_then_clearing_and_activating_with_another_session_shoul_request_to_correct_shop(self): - shopify.ShopifyResource.activate_session(self.session1) - shopify.ShopifyResource.clear_session - shopify.ShopifyResource.activate_session(self.session2) - - self.assertIsNone(ActiveResource.site) - self.assertEqual('https://shop2.myshopify.com/admin', shopify.ShopifyResource.site) - self.assertEqual('https://shop2.myshopify.com/admin', shopify.Shop.site) - - self.assertIsNone(ActiveResource.headers) - self.assertEqual('token2', shopify.ShopifyResource.headers['X-Shopify-Access-Token']) - self.assertEqual('token2', shopify.Shop.headers['X-Shopify-Access-Token']) - - def test_delete_should_send_custom_headers_with_request(self): - shopify.ShopifyResource.activate_session(self.session1) - - org_headers=shopify.ShopifyResource.headers - shopify.ShopifyResource.set_headers({'X-Custom': 'abc'}) - - with patch('shopify.ShopifyResource.connection.delete') as mock: - shopify.ShopifyResource.delete('1') - mock.assert_called_with('/admin/shopify_resources/1.json', {'X-Custom': 'abc'}) - - shopify.ShopifyResource.set_headers(org_headers) - - def test_headers_includes_user_agent(self): - self.assertTrue('User-Agent' in shopify.ShopifyResource.headers) - t = threading.Thread(target=lambda: self.assertTrue('User-Agent' in shopify.ShopifyResource.headers)) - t.start() - t.join() - - def test_headers_is_thread_safe(self): - def testFunc(): - shopify.ShopifyResource.headers['X-Custom'] = 'abc' - self.assertTrue('X-Custom' in shopify.ShopifyResource.headers) - - t1 = threading.Thread(target=testFunc) - t1.start() - t1.join() - - t2 = threading.Thread(target=lambda: self.assertFalse('X-Custom' in shopify.ShopifyResource.headers)) - t2.start() - t2.join() diff --git a/test/blog_test.py b/test/blog_test.py deleted file mode 100644 index 465df603..00000000 --- a/test/blog_test.py +++ /dev/null @@ -1,9 +0,0 @@ -import shopify -from test_helper import TestCase - -class BlogTest(TestCase): - - def test_blog_creation(self): - self.fake('blogs', method='POST', code=202, body=self.load_fixture('blog'), headers={'Content-type': 'application/json'}) - blog = shopify.Blog.create({'title': "Test Blog"}) - self.assertEqual("Test Blog", blog.title) diff --git a/test/carrier_service_test.py b/test/carrier_service_test.py deleted file mode 100644 index a97e1bb5..00000000 --- a/test/carrier_service_test.py +++ /dev/null @@ -1,15 +0,0 @@ -import shopify -from test_helper import TestCase - -class CarrierServiceTest(TestCase): - def test_create_new_carrier_service(self): - self.fake("carrier_services", method='POST', body=self.load_fixture('carrier_service'), headers={'Content-type': 'application/json'}) - - carrier_service = shopify.CarrierService.create({'name': "Some Postal Service"}) - self.assertEqual("Some Postal Service", carrier_service.name) - - def test_get_carrier_service(self): - self.fake("carrier_services/123456", method='GET', body=self.load_fixture('carrier_service')) - - carrier_service = shopify.CarrierService.find(123456) - self.assertEqual("Some Postal Service", carrier_service.name) diff --git a/test/cart_test.py b/test/cart_test.py deleted file mode 100644 index 424c5b6a..00000000 --- a/test/cart_test.py +++ /dev/null @@ -1,13 +0,0 @@ -import shopify -from test_helper import TestCase - -class CartTest(TestCase): - - def test_all_should_return_all_carts(self): - self.fake('carts') - carts = shopify.Cart.find() - self.assertEqual(2, len(carts)) - self.assertEqual(2, carts[0].id) - self.assertEqual("3eed8183d4281db6ea82ee2b8f23e9cc", carts[0].token) - self.assertEqual(1, len(carts[0].line_items)) - self.assertEqual('test', carts[0].line_items[0].title) diff --git a/test/customer_saved_search_test.py b/test/customer_saved_search_test.py deleted file mode 100644 index 4f5f6e2f..00000000 --- a/test/customer_saved_search_test.py +++ /dev/null @@ -1,23 +0,0 @@ -import shopify -from test_helper import TestCase - -class CustomerSavedSearchTest(TestCase): - - def setUp(self): - super(CustomerSavedSearchTest, self).setUp() - self.load_customer_saved_search() - - def test_get_customers_from_customer_saved_search(self): - self.fake('customer_saved_searches/8899730/customers', body=self.load_fixture('customer_saved_search_customers')) - self.assertEqual(1, len(self.customer_saved_search.customers())) - self.assertEqual(112223902, self.customer_saved_search.customers()[0].id) - - def test_get_customers_from_customer_saved_search_with_params(self): - self.fake('customer_saved_searches/8899730/customers.json?limit=1', extension=False, body=self.load_fixture('customer_saved_search_customers')) - customers = self.customer_saved_search.customers(limit = 1) - self.assertEqual(1, len(customers)) - self.assertEqual(112223902, customers[0].id) - - def load_customer_saved_search(self): - self.fake('customer_saved_searches/8899730', body=self.load_fixture('customer_saved_search')) - self.customer_saved_search = shopify.CustomerSavedSearch.find(8899730) diff --git a/test/fixtures/article.json b/test/fixtures/article.json deleted file mode 100644 index 65ac8c6d..00000000 --- a/test/fixtures/article.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "article": { - "author": "Shopify", - "blog_id": 1008414260, - "body_html": null, - "created_at": "2012-07-06T13:57:28-04:00", - "id": 6242736, - "published_at": "2012-07-06T13:57:28-04:00", - "summary_html": null, - "title": "First Post", - "updated_at": "2012-07-06T13:57:51-04:00", - "user_id": null, - "tags": "consequuntur, cupiditate, repellendus" - } -} \ No newline at end of file diff --git a/test/fixtures/articles.json b/test/fixtures/articles.json deleted file mode 100644 index df83a9cb..00000000 --- a/test/fixtures/articles.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "articles": [{ - "author": "Shopify", - "blog_id": 1008414260, - "body_html": null, - "created_at": "2012-07-06T13:57:28-04:00", - "id": 6242736, - "published_at": "2012-07-06T13:57:28-04:00", - "summary_html": null, - "title": "First Post", - "updated_at": "2012-07-06T13:57:51-04:00", - "user_id": null, - "tags": "consequuntur, cupiditate, repellendus" - }, { - "author": "development shop", - "blog_id": 1008414260, - "body_html": null, - "created_at": "2013-04-21T18:10:35-04:00", - "id": 7739673, - "published_at": "2013-04-21T18:10:22-04:00", - "summary_html": null, - "title": "My second blog post", - "updated_at": "2013-04-21T18:10:35-04:00", - "user_id": 2221540, - "tags": "" - }, { - "author": "development shop", - "blog_id": 1008414260, - "body_html": null, - "created_at": "2013-04-21T18:11:19-04:00", - "id": 7739683, - "published_at": "2013-04-21T18:10:45-04:00", - "summary_html": null, - "title": "50% off sale", - "updated_at": "2013-04-21T18:11:19-04:00", - "user_id": 2221540, - "tags": "" - }] -} \ No newline at end of file diff --git a/test/fixtures/asset.json b/test/fixtures/asset.json deleted file mode 100644 index fe29133a..00000000 --- a/test/fixtures/asset.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "asset": { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "value": "\n

Featured Products

\n\n{% tablerow product in collections.frontpage.products cols:3 %}\n {{ product.featured_image | product_img_url: 'small' | img_tag }}\n

{{product.title}}

\n
    \n
  • {{product.price_min | money}}
  • \n
\n{% endtablerow %}\n
\n\n\n
\n \t{% assign article = pages.frontpage %}\n\n
\n {% if article.content != \"\" %}\n\t\t

{{ article.title }}

\n
\n \t\t {{ article.content }}\n \t\t
\n \t{% else %}\n
\n \t In Admin > Blogs & Pages, create a page with the handle frontpage and it will show up here.
\n \t {{ \"Learn more about handles\" | link_to \"http://wiki.shopify.com/Handle\" }}\n
\n \t{% endif %}\n
\n\n
\n\n", - "key": "templates/index.liquid" - } -} diff --git a/test/fixtures/assets.json b/test/fixtures/assets.json deleted file mode 100644 index 282ecafd..00000000 --- a/test/fixtures/assets.json +++ /dev/null @@ -1,136 +0,0 @@ -{ - "assets": [ - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-body-green.gif?1", - "key": "assets/bg-body-green.gif" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-body-orange.gif?1", - "key": "assets/bg-body-orange.gif" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-body-pink.gif?1", - "key": "assets/bg-body-pink.gif" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-body.gif?1", - "key": "assets/bg-body.gif" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-content.gif?1", - "key": "assets/bg-content.gif" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-footer.gif?1", - "key": "assets/bg-footer.gif" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-main.gif?1", - "key": "assets/bg-main.gif" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/bg-sidebar.gif?1", - "key": "assets/bg-sidebar.gif" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/shop.css?1", - "key": "assets/shop.css" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/shop.css.liquid?1", - "key": "assets/shop.css.liquid" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/shop.js?1", - "key": "assets/shop.js" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/sidebar-devider.gif?1", - "key": "assets/sidebar-devider.gif" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": "http://static.shopify.com/s/files/1/6909/3384/t/1/assets/sidebar-menu.jpg?1", - "key": "assets/sidebar-menu.jpg" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "key": "config/settings.html" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "key": "layout/theme.liquid" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "key": "templates/article.liquid" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "key": "templates/blog.liquid" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "key": "templates/cart.liquid" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "key": "templates/collection.liquid" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "key": "templates/index.liquid" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "key": "templates/page.liquid" - }, - { - "created_at": "2010-07-12T15:31:50-04:00", - "updated_at": "2010-07-12T15:31:50-04:00", - "public_url": null, - "key": "templates/product.liquid" - } - ] -} diff --git a/test/fixtures/authors.json b/test/fixtures/authors.json deleted file mode 100644 index fc9db30e..00000000 --- a/test/fixtures/authors.json +++ /dev/null @@ -1 +0,0 @@ -{"authors": ["Shopify", "development shop", "development shop"]} diff --git a/test/fixtures/blog.json b/test/fixtures/blog.json deleted file mode 100644 index df94412c..00000000 --- a/test/fixtures/blog.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "blog": { - "handle": "test-blog", - "created_at": "2012-01-10T17:45:19-05:00", - "title": "Test Blog", - "template_suffix": null, - "updated_at": "2012-01-10T17:45:19-05:00", - "feedburner_location": null, - "id": 1008414260, - "feedburner": null, - "commentable": "no" - } -} \ No newline at end of file diff --git a/test/fixtures/blogs.json b/test/fixtures/blogs.json deleted file mode 100644 index 3f779b25..00000000 --- a/test/fixtures/blogs.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "blogs": [{ - "handle": "test-blog", - "created_at": "2012-01-10T17:45:19-05:00", - "title": "Test Blog", - "template_suffix": null, - "updated_at": "2012-01-10T17:45:19-05:00", - "feedburner_location": null, - "id": 1008414260, - "feedburner": null, - "commentable": "no" - }] -} \ No newline at end of file diff --git a/test/fixtures/carrier_service.json b/test/fixtures/carrier_service.json deleted file mode 100644 index b3f3b5f4..00000000 --- a/test/fixtures/carrier_service.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "carrier_service": { - "name": "Some Postal Service", - "id": 123456, - "callback_url": "http://google.com", - "format": "json", - "service_discovery": true - } -} diff --git a/test/fixtures/carts.json b/test/fixtures/carts.json deleted file mode 100644 index 64d51246..00000000 --- a/test/fixtures/carts.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "carts": [ - { - "id": 2, - "note": null, - "token": "3eed8183d4281db6ea82ee2b8f23e9cc", - "updated_at": "2012-02-13T14:39:37-05:00", - "line_items": - [ - { - "id": 1, - "title": "test", - "price": "1.00", - "line_price": "1.00", - "quantity": 1, - "sku": "", - "grams": 1000, - "vendor": "test", - "variant_id": 1 - } - ] - }, - { - "id": 1, - "note": "", - "token": "49801807939c296be1e9a4bf6783a705", - "updated_at": "2012-02-13T14:39:12-05:00", - "line_items":[ - { - "id": 1, - "title": "test", - "price": "1.00", - "line_price": "1.00", - "quantity": 1, - "sku": "", - "grams": 1000, - "vendor": "test", - "variant_id": 1 - } - ] - } - ] -} \ No newline at end of file diff --git a/test/fixtures/customer_saved_search.json b/test/fixtures/customer_saved_search.json deleted file mode 100644 index c8b0cbaa..00000000 --- a/test/fixtures/customer_saved_search.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "customer_saved_search": { - "created_at": "2013-01-21T13:26:12-05:00", - "id": 8899730, - "name": "Accepts Marketing", - "updated_at": "2013-01-21T13:26:12-05:00", - "query": "accepts_marketing:1" - } -} diff --git a/test/fixtures/customer_saved_search_customers.json b/test/fixtures/customer_saved_search_customers.json deleted file mode 100644 index ca07c424..00000000 --- a/test/fixtures/customer_saved_search_customers.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "customers": [ - { - "accepts_marketing": true, - "created_at": "2013-01-29T16:33:35-05:00", - "email": "john.smith@gmail.com", - "first_name": "John", - "id": 112223902, - "last_name": "Smith", - "last_order_id": null, - "multipass_identifier": null, - "note": "This is sample note", - "orders_count": 0, - "state": "disabled", - "total_spent": "0.00", - "updated_at": "2013-03-05T17:00:05-05:00", - "verified_email": true, - "tags": "Buyer, Canadian", - "last_order_name": null, - "default_address": { - "address1": "1234 Simple Road", - "address2": null, - "city": "Ottawa", - "company": null, - "country": "Canada", - "first_name": "John", - "id": 152583148, - "last_name": "Smith", - "phone": "555-555-5555", - "province": "Ontario", - "zip": "K2H 0A0", - "name": "John Smith", - "province_code": "ON", - "country_code": "CA", - "country_name": "Canada", - "default": true - }, - "addresses": [ - { - "address1": "1234 Simple Road", - "address2": null, - "city": "Ottawa", - "company": null, - "country": "Canada", - "first_name": "John", - "id": 152583148, - "last_name": "Smith", - "phone": "555-555-5555", - "province": "Ontario", - "zip": "K2H 0A0", - "name": "John Smith", - "province_code": "ON", - "country_code": "CA", - "country_name": "Canada", - "default": true - } - ] - } - ] -} diff --git a/test/fixtures/events.json b/test/fixtures/events.json deleted file mode 100644 index 24561f50..00000000 --- a/test/fixtures/events.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "events": [ - { - "verb": "placed", - "created_at": "2008-01-10T11:00:00-05:00", - "body": null, - "subject_id": 450789469, - "id": 852065041, - "subject_type": "Order", - "message": "Order was placed" - }, - { - "verb": "confirmed", - "created_at": "2008-01-10T11:00:00-05:00", - "body": null, - "subject_id": 450789469, - "id": 164748010, - "subject_type": "Order", - "message": "Received new order #1001 by Bob Norman" - }, - { - "verb": "authorization_success", - "created_at": "2008-01-10T11:00:00-05:00", - "body": null, - "subject_id": 450789469, - "id": 103105390, - "subject_type": "Order", - "message": "The customer successfully authorized us to capture 210.94 USD" - } - ] -} diff --git a/test/fixtures/fulfillment.json b/test/fixtures/fulfillment.json deleted file mode 100644 index 9d7e04d3..00000000 --- a/test/fixtures/fulfillment.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "fulfillment": { - "created_at": "2013-11-01T16:06:08-04:00", - "id": 255858046, - "order_id": 450789469, - "service": "manual", - "status": "pending", - "tracking_company": null, - "updated_at": "2013-11-01T16:06:08-04:00", - "tracking_number": "1Z2345", - "tracking_numbers": [ - "1Z2345" - ], - "tracking_url": "http://www.google.com/search?q=1Z2345", - "tracking_urls": [ - "http://www.google.com/search?q=1Z2345" - ], - "receipt": { - "testcase": true, - "authorization": "123456" - }, - "line_items": [ - { - "fulfillment_service": "manual", - "fulfillment_status": null, - "grams": 200, - "id": 466157049, - "price": "199.00", - "product_id": 632910392, - "quantity": 1, - "requires_shipping": true, - "sku": "IPOD2008GREEN", - "title": "IPod Nano - 8gb", - "variant_id": 39072856, - "variant_title": "green", - "vendor": null, - "name": "IPod Nano - 8gb - green", - "variant_inventory_management": "shopify", - "properties": [ - { - "name": "Custom Engraving", - "value": "Happy Birthday" - } - ], - "product_exists": true - } - ] - } -} \ No newline at end of file diff --git a/test/fixtures/fulfillment_service.json b/test/fixtures/fulfillment_service.json deleted file mode 100644 index ae6e9c10..00000000 --- a/test/fixtures/fulfillment_service.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "fulfillment_service": { - "name": "SomeService", - "id": 123456, - "inventory_management": false, - "tracking_support": true, - "requires_shipping_method": false, - "format": "json" - } -} diff --git a/test/fixtures/image.json b/test/fixtures/image.json deleted file mode 100644 index 8da79add..00000000 --- a/test/fixtures/image.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "image": { - "created_at": "2014-01-10T16:15:40-05:00", - "id": 850703190, - "position": 1, - "product_id": 632910392, - "updated_at": "2014-01-10T16:15:40-05:00", - "src": "http://cdn.shopify.com/s/files/1/0006/9093/3842/products/ipod-nano.png?v=1389388540" - } -} diff --git a/test/fixtures/images.json b/test/fixtures/images.json deleted file mode 100644 index 57ff16c8..00000000 --- a/test/fixtures/images.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "images": [ - { - "created_at": "2014-01-17T16:11:52-05:00", - "id": 850703190, - "position": 1, - "product_id": 632910392, - "updated_at": "2014-01-17T16:11:52-05:00", - "src": "http://cdn.shopify.com/s/files/1/0006/9093/3842/products/ipod-nano.png?v=1389993112" - }, - { - "created_at": "2014-01-17T16:11:52-05:00", - "id": 562641783, - "position": 2, - "product_id": 632910392, - "updated_at": "2014-01-17T16:11:52-05:00", - "src": "http://cdn.shopify.com/s/files/1/0006/9093/3842/products/ipod-nano-2.png?v=1389993112" - } - ] -} diff --git a/test/fixtures/metafield.json b/test/fixtures/metafield.json deleted file mode 100644 index b096d9df..00000000 --- a/test/fixtures/metafield.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "metafields": { - "created_at": "2011-10-20T14:05:13-04:00", - "updated_at": "2011-10-20T14:05:13-04:00", - "namespace": "contact", - "id": 721389482, - "value": "123@example.com", - "description": null, - "key": "email", - "value_type": "string" - } -} diff --git a/test/fixtures/metafields.json b/test/fixtures/metafields.json deleted file mode 100644 index 78995109..00000000 --- a/test/fixtures/metafields.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "metafields": [ - { - "created_at": "2011-10-20T14:05:13-04:00", - "updated_at": "2011-10-20T14:05:13-04:00", - "namespace": "affiliates", - "id": 721389482, - "value": "app_key", - "description": null, - "key": "app_key", - "value_type": "string" - }, - { - "created_at": "2011-10-20T14:05:13-04:00", - "updated_at": "2011-10-20T14:05:13-04:00", - "namespace": "contact", - "id": 721389480, - "value": "1231231231", - "description": null, - "key": "phone", - "value_type": "string" - } - ] -} diff --git a/test/fixtures/order.json b/test/fixtures/order.json deleted file mode 100644 index 967b5498..00000000 --- a/test/fixtures/order.json +++ /dev/null @@ -1,275 +0,0 @@ -{ - "order": { - "buyer_accepts_marketing": false, - "cancel_reason": null, - "cancelled_at": null, - "cart_token": "68778783ad298f1c80c3bafcddeea02f", - "checkout_token": null, - "closed_at": null, - "confirmed": false, - "created_at": "2008-01-10T11:00:00-05:00", - "currency": "USD", - "email": "bob.norman@hostmail.com", - "financial_status": "authorized", - "fulfillment_status": null, - "gateway": "authorize_net", - "id": 450789469, - "landing_site": "http://www.example.com?source=abc", - "location_id": null, - "name": "#1001", - "note": null, - "number": 1, - "reference": "fhwdgads", - "referring_site": "http://www.otherexample.com", - "source": null, - "subtotal_price": "398.00", - "taxes_included": false, - "test": false, - "token": "b1946ac92492d2347c6235b4d2611184", - "total_discounts": "0.00", - "total_line_items_price": "398.00", - "total_price": "409.94", - "total_price_usd": "409.94", - "total_tax": "11.94", - "total_weight": 0, - "updated_at": "2008-01-10T11:00:00-05:00", - "user_id": null, - "browser_ip": null, - "landing_site_ref": "abc", - "order_number": 1001, - "discount_codes": [ - { - "code": "TENOFF", - "amount": "10.00" - } - ], - "note_attributes": [ - { - "name": "custom engraving", - "value": "Happy Birthday" - }, - { - "name": "colour", - "value": "green" - } - ], - "processing_method": "direct", - "checkout_id": 450789469, - "source_name": "web", - "tax_lines": [ - { - "price": "11.94", - "rate": 0.06, - "title": "State Tax" - } - ], - "line_items": [ - { - "fulfillment_service": "manual", - "fulfillment_status": null, - "grams": 200, - "id": 466157049, - "price": "199.00", - "product_id": 632910392, - "quantity": 1, - "requires_shipping": true, - "sku": "IPOD2008GREEN", - "title": "IPod Nano - 8gb", - "variant_id": 39072856, - "variant_title": "green", - "vendor": null, - "name": "IPod Nano - 8gb - green", - "variant_inventory_management": "shopify", - "properties": [ - { - "name": "Custom Engraving", - "value": "Happy Birthday" - } - ], - "product_exists": true - }, - { - "fulfillment_service": "manual", - "fulfillment_status": null, - "grams": 200, - "id": 518995019, - "price": "199.00", - "product_id": 632910392, - "quantity": 1, - "requires_shipping": true, - "sku": "IPOD2008RED", - "title": "IPod Nano - 8gb", - "variant_id": 49148385, - "variant_title": "red", - "vendor": null, - "name": "IPod Nano - 8gb - red", - "variant_inventory_management": "shopify", - "properties": [ - - ], - "product_exists": true - }, - { - "fulfillment_service": "manual", - "fulfillment_status": null, - "grams": 200, - "id": 703073504, - "price": "199.00", - "product_id": 632910392, - "quantity": 1, - "requires_shipping": true, - "sku": "IPOD2008BLACK", - "title": "IPod Nano - 8gb", - "variant_id": 457924702, - "variant_title": "black", - "vendor": null, - "name": "IPod Nano - 8gb - black", - "variant_inventory_management": "shopify", - "properties": [ - - ], - "product_exists": true - } - ], - "shipping_lines": [ - { - "code": "Free Shipping", - "price": "0.00", - "source": "shopify", - "title": "Free Shipping" - } - ], - "payment_details": { - "avs_result_code": null, - "credit_card_bin": null, - "cvv_result_code": null, - "credit_card_number": "XXXX-XXXX-XXXX-4242", - "credit_card_company": "Visa" - }, - "billing_address": { - "address1": "Chestnut Street 92", - "address2": "", - "city": "Louisville", - "company": null, - "country": "United States", - "first_name": "Bob", - "last_name": "Norman", - "latitude": "45.41634", - "longitude": "-75.6868", - "phone": "555-625-1199", - "province": "Kentucky", - "zip": "40202", - "name": "Bob Norman", - "country_code": "US", - "province_code": "KY" - }, - "shipping_address": { - "address1": "Chestnut Street 92", - "address2": "", - "city": "Louisville", - "company": null, - "country": "United States", - "first_name": "Bob", - "last_name": "Norman", - "latitude": "45.41634", - "longitude": "-75.6868", - "phone": "555-625-1199", - "province": "Kentucky", - "zip": "40202", - "name": "Bob Norman", - "country_code": "US", - "province_code": "KY" - }, - "fulfillments": [ - { - "created_at": "2014-01-22T15:58:27-05:00", - "id": 255858046, - "order_id": 450789469, - "service": "manual", - "status": "failure", - "tracking_company": null, - "updated_at": "2014-01-22T15:58:27-05:00", - "tracking_number": "1Z2345", - "tracking_numbers": [ - "1Z2345" - ], - "tracking_url": "http://wwwapps.ups.com/etracking/tracking.cgi?InquiryNumber1=1Z2345&TypeOfInquiryNumber=T&AcceptUPSLicenseAgreement=yes&submit=Track", - "tracking_urls": [ - "http://wwwapps.ups.com/etracking/tracking.cgi?InquiryNumber1=1Z2345&TypeOfInquiryNumber=T&AcceptUPSLicenseAgreement=yes&submit=Track" - ], - "receipt": { - "testcase": true, - "authorization": "123456" - }, - "line_items": [ - { - "fulfillment_service": "manual", - "fulfillment_status": null, - "grams": 200, - "id": 466157049, - "price": "199.00", - "product_id": 632910392, - "quantity": 1, - "requires_shipping": true, - "sku": "IPOD2008GREEN", - "title": "IPod Nano - 8gb", - "variant_id": 39072856, - "variant_title": "green", - "vendor": null, - "name": "IPod Nano - 8gb - green", - "variant_inventory_management": "shopify", - "properties": [ - { - "name": "Custom Engraving", - "value": "Happy Birthday" - } - ], - "product_exists": true - } - ] - } - ], - "client_details": { - "accept_language": null, - "browser_ip": "0.0.0.0", - "session_hash": null, - "user_agent": null - }, - "customer": { - "accepts_marketing": false, - "created_at": "2014-01-22T15:58:27-05:00", - "email": "bob.norman@hostmail.com", - "first_name": "Bob", - "id": 207119551, - "last_name": "Norman", - "last_order_id": null, - "multipass_identifier": null, - "note": null, - "orders_count": 0, - "state": "disabled", - "total_spent": "0.00", - "updated_at": "2014-01-22T15:58:27-05:00", - "verified_email": true, - "tags": "", - "last_order_name": null, - "default_address": { - "address1": "Chestnut Street 92", - "address2": "", - "city": "Louisville", - "company": null, - "country": "United States", - "first_name": null, - "id": 207119551, - "last_name": null, - "phone": "555-625-1199", - "province": "Kentucky", - "zip": "40202", - "name": null, - "province_code": "KY", - "country_code": "US", - "country_name": "United States", - "default": true - } - } - } -} diff --git a/test/fixtures/order_risk.json b/test/fixtures/order_risk.json deleted file mode 100644 index 3e5118a3..00000000 --- a/test/fixtures/order_risk.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "risk": { - "cause_cancel": true, - "checkout_id": null, - "display": true, - "id": 284138680, - "message": "This order was placed from a proxy IP", - "order_id": 450789469, - "recommendation": "cancel", - "score": "1.0", - "source": "External", - "merchant_message": "This order was placed from a proxy IP" - } -} diff --git a/test/fixtures/order_risks.json b/test/fixtures/order_risks.json deleted file mode 100644 index 7ecd2dcd..00000000 --- a/test/fixtures/order_risks.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "risks": [ - { - "cause_cancel": true, - "checkout_id": null, - "display": true, - "id": 284138680, - "message": "This order was placed from a proxy IP", - "order_id": 450789469, - "recommendation": "cancel", - "score": "1.0", - "source": "External", - "merchant_message": "This order was placed from a proxy IP" - }, - { - "cause_cancel": true, - "checkout_id": null, - "display": true, - "id": 432527878, - "message": "This order came from an anonymous proxy", - "order_id": 450789469, - "recommendation": "cancel", - "score": "1.0", - "source": "External", - "merchant_message": "This order came from an anonymous proxy" - } - ] -} diff --git a/test/fixtures/product.json b/test/fixtures/product.json deleted file mode 100644 index 52dadedd..00000000 --- a/test/fixtures/product.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "product": { - "product_type": "Cult Products", - "handle": "ipod-nano", - "created_at": "2011-10-20T14:05:13-04:00", - "body_html": "

It's the small iPod with one very big idea: Video. Now the world's most popular music player, available in 4GB and 8GB models, lets you enjoy TV shows, movies, video podcasts, and more. The larger, brighter display means amazing picture quality. In six eye-catching colors, iPod nano is stunning all around. And with models starting at just $149, little speaks volumes.

", - "title": "IPod Nano - 8GB", - "template_suffix": null, - "updated_at": "2011-10-20T14:05:13-04:00", - "id": 632910392, - "tags": "Emotive, Flash Memory, MP3, Music", - "images": [ - { - "position": 1, - "created_at": "2011-10-20T14:05:13-04:00", - "product_id": 632910392, - "updated_at": "2011-10-20T14:05:13-04:00", - "src": "http://static.shopify.com/s/files/1/6909/3384/products/ipod-nano.png?0", - "id": 850703190 - } - ], - "variants": [ - { - "position": 1, - "price": "199.00", - "product_id": 632910392, - "created_at": "2011-10-20T14:05:13-04:00", - "requires_shipping": true, - "title": "Pink", - "inventory_quantity": 10, - "compare_at_price": null, - "inventory_policy": "continue", - "updated_at": "2011-10-20T14:05:13-04:00", - "inventory_management": "shopify", - "id": 808950810, - "taxable": true, - "grams": 200, - "sku": "IPOD2008PINK", - "option1": "Pink", - "fulfillment_service": "manual", - "option2": null, - "option3": null - }, - { - "position": 2, - "price": "199.00", - "product_id": 632910392, - "created_at": "2011-10-20T14:05:13-04:00", - "requires_shipping": true, - "title": "Red", - "inventory_quantity": 20, - "compare_at_price": null, - "inventory_policy": "continue", - "updated_at": "2011-10-20T14:05:13-04:00", - "inventory_management": "shopify", - "id": 49148385, - "taxable": true, - "grams": 200, - "sku": "IPOD2008RED", - "option1": "Red", - "fulfillment_service": "manual", - "option2": null, - "option3": null - }, - { - "position": 3, - "price": "199.00", - "product_id": 632910392, - "created_at": "2011-10-20T14:05:13-04:00", - "requires_shipping": true, - "title": "Green", - "inventory_quantity": 30, - "compare_at_price": null, - "inventory_policy": "continue", - "updated_at": "2011-10-20T14:05:13-04:00", - "inventory_management": "shopify", - "id": 39072856, - "taxable": true, - "grams": 200, - "sku": "IPOD2008GREEN", - "option1": "Green", - "fulfillment_service": "manual", - "option2": null, - "option3": null - }, - { - "position": 4, - "price": "199.00", - "product_id": 632910392, - "created_at": "2011-10-20T14:05:13-04:00", - "requires_shipping": true, - "title": "Black", - "inventory_quantity": 40, - "compare_at_price": null, - "inventory_policy": "continue", - "updated_at": "2011-10-20T14:05:13-04:00", - "inventory_management": "shopify", - "id": 457924702, - "taxable": true, - "grams": 200, - "sku": "IPOD2008BLACK", - "option1": "Black", - "fulfillment_service": "manual", - "option2": null, - "option3": null - } - ], - "vendor": "Apple", - "published_at": "2007-12-31T19:00:00-05:00", - "options": [ - { - "name": "Title" - } - ] - } -} diff --git a/test/fixtures/shop.json b/test/fixtures/shop.json deleted file mode 100644 index ee925166..00000000 --- a/test/fixtures/shop.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "shop": { - "name": "Apple Computers", - "city": "Cupertino", - "address1": "1 Infinite Loop", - "zip": "95014", - "created_at": "2007-12-31T19:00:00-05:00", - "shop_owner": "Steve Jobs", - "plan_name": "enterprise", - "public": false, - "country": "US", - "money_with_currency_format": "$ {{amount}} USD", - "money_format": "$ {{amount}}", - "domain": "shop.apple.com", - "taxes_included": null, - "id": 690933842, - "timezone": "(GMT-05:00) Eastern Time (US & Canada)", - "tax_shipping": null, - "phone": null, - "currency": "USD", - "myshopify_domain": "apple.myshopify.com", - "source": null, - "province": "CA", - "email": "steve@apple.com" - } -} diff --git a/test/fixtures/tags.json b/test/fixtures/tags.json deleted file mode 100644 index 876652ef..00000000 --- a/test/fixtures/tags.json +++ /dev/null @@ -1 +0,0 @@ -{"tags": ["consequuntur", "cupiditate", "repellendus"]} diff --git a/test/fixtures/transaction.json b/test/fixtures/transaction.json deleted file mode 100644 index 33a70e9d..00000000 --- a/test/fixtures/transaction.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "transaction": { - "amount": "409.94", - "authorization": "authorization-key", - "created_at": "2005-08-01T11:57:11-04:00", - "gateway": "bogus", - "id": 389404469, - "kind": "authorization", - "location_id": null, - "message": null, - "order_id": 450789469, - "parent_id": null, - "status": "success", - "test": false, - "user_id": null, - "device_id": null, - "receipt": { - "testcase": true, - "authorization": "123456" - }, - "payment_details": { - "avs_result_code": null, - "credit_card_bin": null, - "cvv_result_code": null, - "credit_card_number": "XXXX-XXXX-XXXX-4242", - "credit_card_company": "Visa" - } - } -} \ No newline at end of file diff --git a/test/fixtures/variant.json b/test/fixtures/variant.json deleted file mode 100644 index 173d7c33..00000000 --- a/test/fixtures/variant.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "variant": { - "price": "199.00", - "position": 1, - "created_at": "2011-10-20T14:05:13-04:00", - "title": "Pink", - "requires_shipping": true, - "updated_at": "2011-10-20T14:05:13-04:00", - "inventory_policy": "continue", - "compare_at_price": null, - "inventory_quantity": 10, - "inventory_management": "shopify", - "taxable": true, - "id": 808950810, - "grams": 200, - "sku": "IPOD2008PINK", - "option1": "Pink", - "option2": null, - "fulfillment_service": "manual", - "option3": null - } -} diff --git a/test/fixtures/variants.json b/test/fixtures/variants.json deleted file mode 100644 index 1128180a..00000000 --- a/test/fixtures/variants.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "variants": [ - { - "price": "199.00", - "position": 1, - "created_at": "2011-10-20T14:05:13-04:00", - "title": "Pink", - "requires_shipping": true, - "updated_at": "2011-10-20T14:05:13-04:00", - "inventory_policy": "continue", - "compare_at_price": null, - "inventory_quantity": 10, - "inventory_management": "shopify", - "taxable": true, - "id": 808950810, - "grams": 200, - "sku": "IPOD2008PINK", - "option1": "Pink", - "option2": null, - "fulfillment_service": "manual", - "option3": null - }, - { - "price": "199.00", - "position": 2, - "created_at": "2011-10-20T14:05:13-04:00", - "title": "Red", - "requires_shipping": true, - "updated_at": "2011-10-20T14:05:13-04:00", - "inventory_policy": "continue", - "compare_at_price": null, - "inventory_quantity": 20, - "inventory_management": "shopify", - "taxable": true, - "id": 49148385, - "grams": 200, - "sku": "IPOD2008RED", - "option1": "Red", - "option2": null, - "fulfillment_service": "manual", - "option3": null - }, - { - "price": "199.00", - "position": 3, - "created_at": "2011-10-20T14:05:13-04:00", - "title": "Green", - "requires_shipping": true, - "updated_at": "2011-10-20T14:05:13-04:00", - "inventory_policy": "continue", - "compare_at_price": null, - "inventory_quantity": 30, - "inventory_management": "shopify", - "taxable": true, - "id": 39072856, - "grams": 200, - "sku": "IPOD2008GREEN", - "option1": "Green", - "option2": null, - "fulfillment_service": "manual", - "option3": null - }, - { - "price": "199.00", - "position": 4, - "created_at": "2011-10-20T14:05:13-04:00", - "title": "Black", - "requires_shipping": true, - "updated_at": "2011-10-20T14:05:13-04:00", - "inventory_policy": "continue", - "compare_at_price": null, - "inventory_quantity": 40, - "inventory_management": "shopify", - "taxable": true, - "id": 457924702, - "grams": 200, - "sku": "IPOD2008BLACK", - "option1": "Black", - "option2": null, - "fulfillment_service": "manual", - "option3": null - } - ] -} diff --git a/test/fulfillment_service_test.py b/test/fulfillment_service_test.py deleted file mode 100644 index 12bb42bf..00000000 --- a/test/fulfillment_service_test.py +++ /dev/null @@ -1,15 +0,0 @@ -import shopify -from test_helper import TestCase - -class FulfillmentServiceTest(TestCase): - def test_create_new_fulfillment_service(self): - self.fake("fulfillment_services", method='POST', body=self.load_fixture('fulfillment_service'), headers={'Content-type': 'application/json'}) - - fulfillment_service = shopify.FulfillmentService.create({'name': "SomeService"}) - self.assertEqual("SomeService", fulfillment_service.name) - - def test_get_fulfillment_service(self): - self.fake("fulfillment_services/123456", method='GET', body=self.load_fixture('fulfillment_service')) - - fulfillment_service = shopify.FulfillmentService.find(123456) - self.assertEqual("SomeService", fulfillment_service.name) diff --git a/test/fulfillment_test.py b/test/fulfillment_test.py deleted file mode 100644 index 91c6bed6..00000000 --- a/test/fulfillment_test.py +++ /dev/null @@ -1,31 +0,0 @@ -import shopify -from test_helper import TestCase -from pyactiveresource.activeresource import ActiveResource - -class FulFillmentTest(TestCase): - - def setUp(self): - super(FulFillmentTest, self).setUp() - self.fake("orders/450789469/fulfillments/255858046", method='GET', body=self.load_fixture('fulfillment')) - - def test_able_to_complete_fulfillment(self): - fulfillment = shopify.Fulfillment.find(255858046, order_id=450789469) - - success = self.load_fixture('fulfillment') - success = success.replace('pending','success') - self.fake("orders/450789469/fulfillments/255858046/complete", method='POST', headers={'Content-length':'0', 'Content-type': 'application/json'}, body=success) - - self.assertEqual('pending', fulfillment.status) - fulfillment.complete() - self.assertEqual('success', fulfillment.status) - - def test_able_to_cancel_fulfillment(self): - fulfillment = shopify.Fulfillment.find(255858046, order_id=450789469) - - cancelled = self.load_fixture('fulfillment') - cancelled = cancelled.replace('pending', 'cancelled') - self.fake("orders/450789469/fulfillments/255858046/cancel", method='POST', headers={'Content-length':'0', 'Content-type': 'application/json'}, body=cancelled) - - self.assertEqual('pending', fulfillment.status) - fulfillment.cancel() - self.assertEqual('cancelled', fulfillment.status) diff --git a/test/image_test.py b/test/image_test.py deleted file mode 100644 index 92aabfa0..00000000 --- a/test/image_test.py +++ /dev/null @@ -1,24 +0,0 @@ -import shopify -from test_helper import TestCase - -class ImageTest(TestCase): - - def test_create_image(self): - self.fake("products/632910392/images", method='POST', body=self.load_fixture('image'), headers={'Content-type': 'application/json'}) - image = shopify.Image({'product_id':632910392}) - image.position = 1 - image.attachment = "R0lGODlhbgCMAPf/APbr48VySrxTO7IgKt2qmKQdJeK8lsFjROG5p/nz7Zg3MNmnd7Q1MLNVS9GId71hSJMZIuzTu4UtKbeEeakhKMl8U8WYjfr18YQaIbAf==" - image.save() - - self.assertEqual('http://cdn.shopify.com/s/files/1/0006/9093/3842/products/ipod-nano.png?v=1389388540', image.src) - self.assertEqual(850703190, image.id) - - def test_get_images(self): - self.fake("products/632910392/images", method='GET', body=self.load_fixture('images')) - image = shopify.Image.find(product_id=632910392) - self.assertEqual(2, len(image)) - - def test_get_image(self): - self.fake("products/632910392/images/850703190", method='GET', body=self.load_fixture('image')) - image = shopify.Image.find(850703190, product_id=632910392) - self.assertEqual(850703190, image.id) diff --git a/test/order_risk_test.py b/test/order_risk_test.py deleted file mode 100644 index ad790105..00000000 --- a/test/order_risk_test.py +++ /dev/null @@ -1,42 +0,0 @@ -import shopify -from test_helper import TestCase - -class OrderRiskTest(TestCase): - - def test_create_order_risk(self): - self.fake("orders/450789469/risks", method='POST', body= self.load_fixture('order_risk'), headers={'Content-type': 'application/json'}) - v = shopify.OrderRisk({'order_id':450789469}) - v.message = "This order was placed from a proxy IP" - v.recommendation = "cancel" - v.score = "1.0" - v.source = "External" - v.merchant_message = "This order was placed from a proxy IP" - v.display = True - v.cause_cancel = True - v.save() - - self.assertEqual(284138680, v.id) - - def test_get_order_risks(self): - self.fake("orders/450789469/risks", method='GET', body= self.load_fixture('order_risks')) - v = shopify.OrderRisk.find(order_id=450789469) - self.assertEqual(2, len(v)) - - def test_get_order_risk(self): - self.fake("orders/450789469/risks/284138680", method='GET', body= self.load_fixture('order_risk')) - v = shopify.OrderRisk.find(284138680, order_id=450789469) - self.assertEqual(284138680, v.id) - - def test_delete_order_risk(self): - self.fake("orders/450789469/risks/284138680", method='GET', body= self.load_fixture('order_risk')) - self.fake("orders/450789469/risks/284138680", method='DELETE', body="destroyed") - v = shopify.OrderRisk.find(284138680, order_id=450789469) - v.destroy() - - def test_delete_order_risk(self): - self.fake("orders/450789469/risks/284138680", method='GET', body= self.load_fixture('order_risk')) - self.fake("orders/450789469/risks/284138680", method='PUT', body= self.load_fixture('order_risk'), headers={'Content-type': 'application/json'}) - - v = shopify.OrderRisk.find(284138680, order_id=450789469) - v.position = 3 - v.save() diff --git a/test/order_test.py b/test/order_test.py deleted file mode 100644 index 8b7bca96..00000000 --- a/test/order_test.py +++ /dev/null @@ -1,49 +0,0 @@ -import shopify -from test_helper import TestCase -from pyactiveresource.activeresource import ActiveResource -from pyactiveresource.util import xml_to_dict - -class OrderTest(TestCase): - - def test_should_be_loaded_correctly_from_order_xml(self): - order_xml = """ - - - - size - large - - - """ - order = shopify.Order(xml_to_dict(order_xml)["order"]) - - self.assertEqual(1, len(order.note_attributes)) - - note_attribute = order.note_attributes[0] - self.assertEqual("size", note_attribute.name) - self.assertEqual("large", note_attribute.value) - - def test_should_be_able_to_add_note_attributes_to_an_order(self): - order = shopify.Order() - order.note_attributes = [] - order.note_attributes.append(shopify.NoteAttribute({'name': "color", 'value': "blue"})) - - order_xml = xml_to_dict(order.to_xml()) - note_attributes = order_xml["order"]["note_attributes"] - self.assertTrue(isinstance(note_attributes, list)) - - attribute = note_attributes[0] - self.assertEqual("color", attribute["name"]) - self.assertEqual("blue", attribute["value"]) - - def test_get_order(self): - self.fake('orders/450789469', method='GET', body=self.load_fixture('order')) - order = shopify.Order.find(450789469) - self.assertEqual('bob.norman@hostmail.com', order.email) - - def test_get_order_transaction(self): - self.fake('orders/450789469', method='GET', body=self.load_fixture('order')) - order = shopify.Order.find(450789469) - self.fake('orders/450789469/transactions', method='GET', body=self.load_fixture('transaction')) - transactions = order.transactions() - self.assertEqual("409.94", transactions[0].amount) diff --git a/test/product_test.py b/test/product_test.py deleted file mode 100644 index 89bfbb32..00000000 --- a/test/product_test.py +++ /dev/null @@ -1,42 +0,0 @@ -import shopify -from test_helper import TestCase - -class ProductTest(TestCase): - - def setUp(self): - super(ProductTest, self).setUp() - - self.fake("products/632910392", body=self.load_fixture('product')) - self.product = shopify.Product.find(632910392) - - def test_add_metafields_to_product(self): - self.fake("products/632910392/metafields", method='POST', code=201, body=self.load_fixture('metafield'), headers={'Content-type': 'application/json'}) - - field = self.product.add_metafield(shopify.Metafield({'namespace': "contact", 'key': "email", 'value': "123@example.com", 'value_type': "string"})) - - self.assertFalse(field.is_new()) - self.assertEqual("contact", field.namespace) - self.assertEqual("email", field.key) - self.assertEqual("123@example.com", field.value) - - def test_get_metafields_for_product(self): - self.fake("products/632910392/metafields", body=self.load_fixture('metafields')) - - metafields = self.product.metafields() - - self.assertEqual(2, len(metafields)) - for field in metafields: - self.assertTrue(isinstance(field, shopify.Metafield)) - - def test_update_loaded_variant(self): - self.fake("products/632910392/variants/808950810", method='PUT', code=200, body=self.load_fixture('variant')) - - variant = self.product.variants[0] - variant.price = "0.50" - variant.save - - def test_add_variant_to_product(self): - self.fake("products/632910392/variants", method='POST', body=self.load_fixture('variant'), headers={'Content-type': 'application/json'}) - self.fake("products/632910392/variants/808950810", method='PUT', code=200, body=self.load_fixture('variant'), headers={'Content-type': 'application/json'}) - v = shopify.Variant() - self.assertTrue(self.product.add_variant(v)) diff --git a/test/recurring_charge_test.py b/test/recurring_charge_test.py deleted file mode 100644 index d453c548..00000000 --- a/test/recurring_charge_test.py +++ /dev/null @@ -1,9 +0,0 @@ -import shopify -from test_helper import TestCase - -class RecurringApplicationChargeTest(TestCase): - def test_activate_charge(self): - # Just check that calling activate doesn't raise an exception. - self.fake("recurring_application_charges/35463/activate", method='POST',headers={'Content-length':'0', 'Content-type': 'application/json'}, body=" ") - charge = shopify.RecurringApplicationCharge({'id': 35463}) - charge.activate() diff --git a/test/session_test.py b/test/session_test.py deleted file mode 100644 index 23c51866..00000000 --- a/test/session_test.py +++ /dev/null @@ -1,158 +0,0 @@ -import shopify -from test_helper import TestCase -try: - from hashlib import md5 -except ImportError: - from md5 import md5 -import time - -class SessionTest(TestCase): - - def test_not_be_valid_without_a_url(self): - session = shopify.Session("", "any-token") - self.assertFalse(session.valid) - - def test_not_be_valid_without_token(self): - session = shopify.Session("testshop.myshopify.com") - self.assertFalse(session.valid) - - def test_be_valid_with_any_token_and_any_url(self): - session = shopify.Session("testshop.myshopify.com", "any-token") - self.assertTrue(session.valid) - - def test_not_raise_error_without_params(self): - session = shopify.Session("testshop.myshopify.com", "any-token") - - def test_raise_error_if_params_passed_but_signature_omitted(self): - with self.assertRaises(shopify.ValidationException): - session = shopify.Session("testshop.myshopify.com") - token = session.request_token({'code':'any_code', 'foo': 'bar', 'timestamp':'1234'}) - - def test_setup_api_key_and_secret_for_all_sessions(self): - shopify.Session.setup(api_key="My test key", secret="My test secret") - self.assertEqual("My test key", shopify.Session.api_key) - self.assertEqual("My test secret", shopify.Session.secret) - - def test_use_https_protocol_by_default_for_all_sessions(self): - self.assertEqual('https', shopify.Session.protocol) - - def test_temp_reset_shopify_ShopifyResource_site_to_original_value(self): - shopify.Session.setup(api_key="key", secret="secret") - session1 = shopify.Session('fakeshop.myshopify.com', 'token1') - shopify.ShopifyResource.activate_session(session1) - - assigned_site = "" - with shopify.Session.temp("testshop.myshopify.com", "any-token"): - assigned_site = shopify.ShopifyResource.site - - self.assertEqual('https://testshop.myshopify.com/admin', assigned_site) - self.assertEqual('https://fakeshop.myshopify.com/admin', shopify.ShopifyResource.site) - - def test_temp_reset_shopify_ShopifyResource_site_to_original_value_when_using_a_non_standard_port(self): - shopify.Session.setup(api_key="key", secret="secret") - session1 = shopify.Session('fakeshop.myshopify.com:3000', 'token1') - shopify.ShopifyResource.activate_session(session1) - - assigned_site = "" - with shopify.Session.temp("testshop.myshopify.com", "any-token"): - assigned_site = shopify.ShopifyResource.site - - self.assertEqual('https://testshop.myshopify.com/admin', assigned_site) - self.assertEqual('https://fakeshop.myshopify.com:3000/admin', shopify.ShopifyResource.site) - - def test_temp_works_without_currently_active_session(self): - shopify.ShopifyResource.clear_session() - - assigned_site = "" - with shopify.Session.temp("testshop.myshopify.com", "any-token"): - assigned_site = shopify.ShopifyResource.site - - self.assertEqual('https://testshop.myshopify.com/admin', assigned_site) - self.assertEqual('https://None/admin', shopify.ShopifyResource.site) - - def test_create_permission_url_returns_correct_url_with_single_scope_no_redirect_uri(self): - shopify.Session.setup(api_key="My_test_key", secret="My test secret") - session = shopify.Session('http://localhost.myshopify.com') - scope = ["write_products"] - permission_url = session.create_permission_url(scope) - self.assertEqual("https://localhost.myshopify.com/admin/oauth/authorize?scope=write_products&client_id=My_test_key", permission_url) - - def test_create_permission_url_returns_correct_url_with_single_scope_and_redirect_uri(self): - shopify.Session.setup(api_key="My_test_key", secret="My test secret") - session = shopify.Session('http://localhost.myshopify.com') - scope = ["write_products"] - permission_url = session.create_permission_url(scope, "my_redirect_uri.com") - self.assertEqual("https://localhost.myshopify.com/admin/oauth/authorize?scope=write_products&redirect_uri=my_redirect_uri.com&client_id=My_test_key", permission_url) - - def test_create_permission_url_returns_correct_url_with_dual_scope_no_redirect_uri(self): - shopify.Session.setup(api_key="My_test_key", secret="My test secret") - session = shopify.Session('http://localhost.myshopify.com') - scope = ["write_products","write_customers"] - permission_url = session.create_permission_url(scope) - self.assertEqual("https://localhost.myshopify.com/admin/oauth/authorize?scope=write_products%2Cwrite_customers&client_id=My_test_key", permission_url) - - def test_create_permission_url_returns_correct_url_with_no_scope_no_redirect_uri(self): - shopify.Session.setup(api_key="My_test_key", secret="My test secret") - session = shopify.Session('http://localhost.myshopify.com') - scope = [] - permission_url = session.create_permission_url(scope) - self.assertEqual("https://localhost.myshopify.com/admin/oauth/authorize?scope=&client_id=My_test_key", permission_url) - - def test_raise_exception_if_code_invalid_in_request_token(self): - shopify.Session.setup(api_key="My test key", secret="My test secret") - session = shopify.Session('http://localhost.myshopify.com') - self.fake(None, url='https://localhost.myshopify.com/admin/oauth/access_token', method='POST', code=404, body='{"error" : "invalid_request"}', has_user_agent=False) - - with self.assertRaises(shopify.ValidationException): - session.request_token({'code':'any-code', 'timestamp':'1234'}) - - self.assertFalse(session.valid) - - def test_return_site_for_session(self): - session = shopify.Session("testshop.myshopify.com", "any-token") - self.assertEqual("https://testshop.myshopify.com/admin", session.site) - - def test_return_token_if_signature_is_valid(self): - shopify.Session.secret='secret' - params = {'code': 'any-code', 'timestamp': time.time()} - sorted_params = self.make_sorted_params(params) - signature = md5(shopify.Session.secret + sorted_params).hexdigest() - params['signature'] = signature - - self.fake(None, url='https://localhost.myshopify.com/admin/oauth/access_token', method='POST', body='{"access_token" : "token"}', has_user_agent=False) - session = shopify.Session('http://localhost.myshopify.com') - token = session.request_token(params) - self.assertEqual("token", token) - - def test_raise_error_if_signature_does_not_match_expected(self): - shopify.Session.secret='secret' - params = {'foo': 'hello', 'timestamp': time.time()} - sorted_params = self.make_sorted_params(params) - signature = md5(shopify.Session.secret + sorted_params).hexdigest() - params['signature'] = signature - params['bar'] = 'world' - params['code'] = 'code' - - with self.assertRaises(shopify.ValidationException): - session = shopify.Session('http://localhost.myshopify.com') - session = session.request_token(params) - - def test_raise_error_if_timestamp_is_too_old(self): - shopify.Session.secret='secret' - one_day = 24 * 60 * 60 - params = {'code': 'any-code', 'timestamp': time.time()-(2*one_day)} - sorted_params = self.make_sorted_params(params) - signature = md5(shopify.Session.secret + sorted_params).hexdigest() - params['signature'] = signature - - with self.assertRaises(shopify.ValidationException): - session = shopify.Session('http://localhost.myshopify.com') - session = session.request_token(params) - - - def make_sorted_params(self, params): - sorted_params = "" - for k in sorted(params.keys()): - if k != "signature": - sorted_params += k + "=" + str(params[k]) - return sorted_params diff --git a/test/shop_test.py b/test/shop_test.py deleted file mode 100644 index 66be7d4a..00000000 --- a/test/shop_test.py +++ /dev/null @@ -1,44 +0,0 @@ -import shopify -from test_helper import TestCase - -class ShopTest(TestCase): - def setUp(self): - super(ShopTest, self).setUp() - self.fake("shop") - self.shop = shopify.Shop.current() - - def test_current_should_return_current_shop(self): - self.assertTrue(isinstance(self.shop,shopify.Shop)) - self.assertEqual("Apple Computers", self.shop.name) - self.assertEqual("apple.myshopify.com", self.shop.myshopify_domain) - self.assertEqual(690933842, self.shop.id) - self.assertEqual("2007-12-31T19:00:00-05:00", self.shop.created_at) - self.assertIsNone(self.shop.tax_shipping) - - def test_get_metafields_for_shop(self): - self.fake("metafields") - - metafields = self.shop.metafields() - - self.assertEqual(2, len(metafields)) - for field in metafields: - self.assertTrue(isinstance(field, shopify.Metafield)) - - def test_add_metafield(self): - self.fake("metafields", method='POST', code=201, body=self.load_fixture('metafield'), headers={'Content-type': 'application/json'}) - - field = self.shop.add_metafield( shopify.Metafield({'namespace': "contact", 'key': "email", 'value': "123@example.com", 'value_type': "string"})) - - self.assertFalse(field.is_new()) - self.assertEqual("contact", field.namespace) - self.assertEqual("email", field.key) - self.assertEqual("123@example.com", field.value) - - def test_events(self): - self.fake("events") - - events = self.shop.events() - - self.assertEqual(3, len(events)) - for event in events: - self.assertTrue(isinstance(event, shopify.Event)) diff --git a/test/test_helper.py b/test/test_helper.py deleted file mode 100644 index bd89edcb..00000000 --- a/test/test_helper.py +++ /dev/null @@ -1,56 +0,0 @@ -import os -import sys -import unittest -from pyactiveresource.activeresource import ActiveResource -from pyactiveresource.testing import http_fake -import shopify - -class TestCase(unittest.TestCase): - - def setUp(self): - ActiveResource.site = None - ActiveResource.headers=None - - shopify.ShopifyResource.clear_session() - shopify.ShopifyResource.site = "https://this-is-my-test-show.myshopify.com/admin" - shopify.ShopifyResource.password = None - shopify.ShopifyResource.user = None - - http_fake.initialize() - self.http = http_fake.TestHandler - self.http.set_response(Exception('Bad request')) - self.http.site = 'https://this-is-my-test-show.myshopify.com' - - def load_fixture(self, name, format='json'): - return open(os.path.dirname(__file__)+'/fixtures/%s.%s' % (name, format), 'r').read() - - def fake(self, endpoint, **kwargs): - body = kwargs.pop('body', None) or self.load_fixture(endpoint) - format = kwargs.pop('format','json') - method = kwargs.pop('method','GET') - - if ('extension' in kwargs and not kwargs['extension']): - extension = "" - else: - extension = ".%s" % (kwargs.pop('extension', 'json')) - - url = "https://this-is-my-test-show.myshopify.com/admin/%s%s" % (endpoint, extension) - try: - url = kwargs['url'] - except KeyError: - pass - - headers = {} - if kwargs.pop('has_user_agent', True): - userAgent = 'ShopifyPythonAPI/%s Python/%s' % (shopify.VERSION, sys.version.split(' ', 1)[0]) - headers['User-agent'] = userAgent - - try: - headers.update(kwargs['headers']) - except KeyError: - pass - - code = kwargs.pop('code', 200) - - self.http.respond_to( - method, url, headers, body=body, code=code) diff --git a/test/transaction_test.py b/test/transaction_test.py deleted file mode 100644 index ae32677f..00000000 --- a/test/transaction_test.py +++ /dev/null @@ -1,11 +0,0 @@ -import shopify -from test_helper import TestCase - -class TransactionTest(TestCase): - def setUp(self): - super(TransactionTest, self).setUp() - self.fake("orders/450789469/transactions/389404469", method='GET', body=self.load_fixture('transaction')) - - def test_should_find_a_specific_transaction(self): - transaction = shopify.Transaction.find(389404469, order_id=450789469) - self.assertEqual("409.94", transaction.amount) diff --git a/test/variant_test.py b/test/variant_test.py deleted file mode 100644 index dd9d55c2..00000000 --- a/test/variant_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import shopify -from test_helper import TestCase - -class VariantTest(TestCase): - - def test_get_variants(self): - self.fake("products/632910392/variants", method='GET', body=self.load_fixture('variants')) - v = shopify.Variant.find(product_id = 632910392) - - def test_get_variant_namespaced(self): - self.fake("products/632910392/variants/808950810", method='GET', body=self.load_fixture('variant')) - v = shopify.Variant.find(808950810, product_id = 632910392) - - def test_update_variant_namespace(self): - self.fake("products/632910392/variants/808950810", method='GET', body=self.load_fixture('variant')) - v = shopify.Variant.find(808950810, product_id = 632910392) - - self.fake("products/632910392/variants/808950810", method='PUT', body=self.load_fixture('variant'), headers={'Content-type': 'application/json'}) - v.save() - - def test_create_variant(self): - self.fake("products/632910392/variants", method='POST', body=self.load_fixture('variant'), headers={'Content-type': 'application/json'}) - v = shopify.Variant({'product_id':632910392}) - v.save() - - def test_create_variant_then_add_parent_id(self): - self.fake("products/632910392/variants", method='POST', body=self.load_fixture('variant'), headers={'Content-type': 'application/json'}) - v = shopify.Variant() - v.product_id = 632910392 - v.save() - - def test_get_variant(self): - self.fake("variants/808950810", method='GET', body=self.load_fixture('variant')) - v = shopify.Variant.find(808950810) From 309956ac7461f249e22e79ab20b54aea902af2cb Mon Sep 17 00:00:00 2001 From: Helen Tran Date: Mon, 23 Jun 2014 12:24:04 -0400 Subject: [PATCH 2/8] Add config --- _config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 _config.yml diff --git a/_config.yml b/_config.yml new file mode 100644 index 00000000..911bafd8 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +markdown: kramdown \ No newline at end of file From 4fd10dd9ad5049b420345b8ec4d6a78188fe5b3e Mon Sep 17 00:00:00 2001 From: Helen Tran Date: Mon, 23 Jun 2014 12:29:59 -0400 Subject: [PATCH 3/8] Rename stuff --- README.md => index.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README.md => index.md (100%) diff --git a/README.md b/index.md similarity index 100% rename from README.md rename to index.md From fd361d5d565d97c44159f91041377e10f036f7a7 Mon Sep 17 00:00:00 2001 From: Helen Tran Date: Thu, 26 Jun 2014 15:01:39 -0400 Subject: [PATCH 4/8] Adjust readme --- _layouts/index.html | 1 + index.md | 266 +++++++++++++++++--------------------------- 2 files changed, 103 insertions(+), 164 deletions(-) diff --git a/_layouts/index.html b/_layouts/index.html index 74e1d9c8..13fcd884 100644 --- a/_layouts/index.html +++ b/_layouts/index.html @@ -24,6 +24,7 @@

{{ site.github.project_title }}

{{ site.github.project_tagline }}

+ Documentation Download ZIP Github Repo diff --git a/index.md b/index.md index d68b7b08..a7f30a78 100644 --- a/index.md +++ b/index.md @@ -2,241 +2,179 @@ layout: index --- -# Shopify API +The ShopifyAPI library allows Python developers to programmatically access the admin section of stores. -The ShopifyAPI library allows Python developers to programmatically -access the admin section of stores. +The API is accessed using pyactiveresource in order to provide an interface similar to the [ruby Shopify API](https://github.com/shopify/shopify_api) gem. The data itself is sent as XML over HTTP to communicate with Shopify, which provides a web service that follows the REST principles as much as possible. -The API is accessed using pyactiveresource in order to provide an -interface similar to the -[ruby Shopify API](https://github.com/shopify/shopify_api) gem. -The data itself is sent as XML over HTTP to communicate with Shopify, -which provides a web service that follows the REST principles as -much as possible. +## Installation -## Usage - -### Requirements - -All API usage happens through Shopify applications, created by -either shop owners for their own shops, or by Shopify Partners for -use by other shop owners: +To easily install or upgrade to the latest release, use +[pip](http://www.pip-installer.org/) -* Shop owners can create applications for themselves through their -own admin: -* Shopify Partners create applications through their admin: - + shell + pip install --upgrade ShopifyAPI -For more information and detailed documentation about the API visit - +or [easy_install](http://packages.python.org/distribute/easy_install.html) -### Installation + shell + easy_install -U ShopifyAPI -To easily install or upgrade to the latest release, use -[pip](http://www.pip-installer.org/) +## Usage -```shell -pip install --upgrade ShopifyAPI -``` +### Requirements -or [easy_install](http://packages.python.org/distribute/easy_install.html) +All API usage happens through Shopify applications, created by either shop owners for their own shops, or by Shopify Partners for use by other shop owners: -```shell -easy_install -U ShopifyAPI -``` +* Shop owners can create applications for themselves through their own admin: +* Shopify Partners create applications through their admin: ### Getting Started -ShopifyAPI uses pyactiveresource to communicate with the REST web -service. pyactiveresource has to be configured with a fully authorized -URL of a particular store first. To obtain that URL you can follow -these steps: +ShopifyAPI uses pyactiveresource to communicate with the REST web service. pyactiveresource has to be configured with a fully authorized URL of a particular store first. To obtain that URL you can follow these steps: -1. First create a new application in either the partners admin or - your store admin. For a private App you'll need the API_KEY and - the PASSWORD otherwise you'll need the API_KEY and SHARED_SECRET. +1. First create a new application in either the partners admin or your store admin. For a private App you'll need the API_KEY and the PASSWORD otherwise you'll need the API_KEY and SHARED_SECRET. 2. For a private App you just need to set the base site url as follows: - ```python - shop_url = "https://%s:%s@SHOP_NAME.myshopify.com/admin" % (API_KEY, PASSWORD) - shopify.ShopifyResource.set_site(shop_url) - ``` + python + shop_url = "https://%s:%s@SHOP_NAME.myshopify.com/admin" % (API_KEY, PASSWORD) + shopify.ShopifyResource.set_site(shop_url) + + That's it you're done, skip to step 6 and start using the API! For a partner App you will need to supply two parameters to the Session class before you instantiate it: - That's it you're done, skip to step 6 and start using the API! - For a partner App you will need to supply two parameters to the - Session class before you instantiate it: - - ```python - shopify.Session.setup(api_key=API_KEY, secret=SHARED_SECRET) - ``` + python + shopify.Session.setup(api_key=API_KEY, secret=SHARED_SECRET) -3. In order to access a shop's data, apps need an access token from that - specific shop. This is a two-stage process. Before interacting with - a shop for the first time an app should redirect the user to the - following URL: +3. In order to access a shop's data, apps need an access token from that specific shop. This is a two-stage process. Before interacting with a shop for the first time an app should redirect the user to the following URL: - `GET https://SHOP_NAME.myshopify.com/admin/oauth/authorize` + GET https://SHOP_NAME.myshopify.com/admin/oauth/authorize with the following parameters: - ``` - * client_id – Required – The API key for your app - * scope – Required – The list of required scopes (explained here: http://docs.shopify.com/api/tutorials/oauth) - * redirect_uri – Optional – The URL that the merchant will be sent to once authentication is complete. Defaults to the URL specified in the application settings and must be the same host as that URL. - ``` + * `client_id` – Required – The API key for your app + * `scope` – Required – The list of required scopes (explained here: http://docs.shopify.com/api/tutorials/oauth) + * `redirect_uri` – Optional – The URL that the merchant will be sent to once authentication is complete. Defaults to the URL specified in the application settings and must be the same host as that URL. - We've added the create_permision_url method to make this easier, first - instantiate your session object: + We've added the create_permision_url method to make this easier, first instantiate your session object: - ```python - session = shopify.Session("SHOP_NAME.myshopify.com") - ``` - + python + session = shopify.Session("SHOP_NAME.myshopify.com") + Then call: - ```python - scope=["write_products"] - permission_url = session.create_permission_url(scope) - ``` - + python + scope=["write_products"] + permission_url = session.create_permission_url(scope) + or if you want a custom redirect_uri: - ```python - permission_url = session.create_permission_url(scope, "https://my_redirect_uri.com") - ``` + python + permission_url = session.create_permission_url(scope, "https://my_redirect_uri.com") -4. Once authorized, the shop redirects the owner to the return URL of your - application with a parameter named 'code'. This is a temporary token - that the app can exchange for a permanent access token. Make the following call: +4. Once authorized, the shop redirects the owner to the return URL of your application with a parameter named 'code'. This is a temporary token that the app can exchange for a permanent access token. Make the following call: - `POST https://SHOP_NAME.myshopify.com/admin/oauth/access_token` + POST https://SHOP_NAME.myshopify.com/admin/oauth/access_token with the following parameters: - ``` - * client_id – Required – The API key for your app - * client_secret – Required – The shared secret for your app - * code – Required – The code you received in step 3 - ``` + * `client_id` – Required – The API key for your app + * `client_secret` – Required – The shared secret for your app + * `code` – Required – The code you received in step 3 and you'll get your permanent access token back in the response. - There is a method to make the request and get the token for you. Pass - all the params received from the previous call (shop, code, timestamp, - signature) as a dictionary and the method will verify - the params, extract the temp code and then request your token: + There is a method to make the request and get the token for you. Pass all the params received from the previous call (shop, code, timestamp, signature) as a dictionary and the method will verify the params, extract the temp code and then request your token: - ```python - token = session.request_token(params) - ``` - - This method will save the token to the session object - and return it. For future sessions simply pass the token when - creating the session object. - - ```python - session = shopify.Session("SHOP_NAME.myshopify.com", token) - ``` + python + token = session.request_token(params) + + This method will save the token to the session object and return it. For future sessions simply pass the token when creating the session object. + python + session = shopify.Session("SHOP_NAME.myshopify.com", token) + 5. The session must be activated before use: - ```python - shopify.ShopifyResource.activate_session(session) - ``` - + python + shopify.ShopifyResource.activate_session(session) + 6. Now you're ready to make authorized API requests to your shop! Data is returned as ActiveResource instances: - ```python - shop = shopify.Shop.current - - # Get a specific product - product = shopify.Product.find(179761209) - - # Create a new product - new_product = shopify.Product() - new_product.title = "Burton Custom Freestyle 151" - new_product.product_type = "Snowboard" - new_product.vendor = "Burton" - success = new_product.save() #returns false if the record is invalid - # or - if new_product.errors: - #something went wrong, see new_product.errors.full_messages() for example - - # Update a product - product.handle = "burton-snowboard" - product.save() - ``` - + python + shop = shopify.Shop.current + + # Get a specific product + product = shopify.Product.find(179761209) + + # Create a new product + new_product = shopify.Product() + new_product.title = "Burton Custom Freestyle 151" + new_product.product_type = "Snowboard" + new_product.vendor = "Burton" + success = new_product.save() #returns false if the record is invalid + # or + if new_product.errors: + #something went wrong, see new_product.errors.full_messages() for example + + # Update a product + product.handle = "burton-snowboard" + product.save() + Alternatively, you can use temp to initialize a Session and execute a command which also handles temporarily setting ActiveResource::Base.site: - ```python - with shopify.Session.temp("SHOP_NAME.myshopify.com", token): - product = shopify.Product.find() - ``` - + python + with shopify.Session.temp("SHOP_NAME.myshopify.com", token): + product = shopify.Product.find() + 7. If you want to work with another shop, you'll first need to clear the session:: - ```python - shopify.ShopifyResource.clear_session - ``` - + python + shopify.ShopifyResource.clear_session + ### Console -This package also includes the `shopify_api.py` script to make it easy to -open up an interactive console to use the API with a shop. +This package also includes the `shopify_api.py` script to make it easy to open up an interactive console to use the API with a shop. -1. Obtain a private API key and password to use with your shop - (step 2 in "Getting Started") +1. Obtain a private API key and password to use with your shop (step 2 in "Getting Started") -2. Use the `shopify_api.py` script to save the credentials for the - shop to quickly log in. The script uses [PyYAML](http://pyyaml.org/) to save - and load connection configurations in the same format as the ruby - shopify\_api. - - ```shell - shopify_api.py add yourshopname - ``` +2. Use the `shopify_api.py` script to save the credentials for the shop to quickly log in. The script uses [PyYAML](http://pyyaml.org/) to save and load connection configurations in the same format as the ruby shopify\_api. + shell + shopify_api.py add yourshopname + Follow the prompts for the shop domain, API key and password. 3. Start the console for the connection. - ```shell - shopify_api.py console - ``` - + shell + shopify_api.py console + 4. To see the full list of commands, type: - ```shell - shopify_api.py help - ``` - + shell + shopify_api.py help + ## Using Development Version The development version can be built using -```shell -python setup.py sdist -``` + shell + python setup.py sdist then the package can be installed using pip -```shell -pip install --upgrade dist/ShopifyAPI-*.tar.gz -``` + shell + pip install --upgrade dist/ShopifyAPI-*.tar.gz or easy_install -```shell -easy_install -U dist/ShopifyAPI-*.tar.gz -``` + shell + easy_install -U dist/ShopifyAPI-*.tar.gz -Note Use the `bin/shopify_api.py` script when running from the source tree. -It will add the lib directory to start of sys.path, so the installed -version won't be used. +#### Note +Use the `bin/shopify_api.py` script when running from the source tree. It will add the lib directory to start of sys.path, so the installed version won't be used. ## Limitations From 2b3ace824879848c03ec8209c8df634836795384 Mon Sep 17 00:00:00 2001 From: Helen Tran Date: Thu, 26 Jun 2014 15:27:14 -0400 Subject: [PATCH 5/8] Adjust footer --- _includes/footer.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_includes/footer.html b/_includes/footer.html index 25c856d0..eb2c2acb 100644 --- a/_includes/footer.html +++ b/_includes/footer.html @@ -4,12 +4,12 @@ -
- Want to contribute? Join the team -
+
+ Want to contribute? Join the team +
\ No newline at end of file From 624366218b8a2a59fa86e71aedacfb868d6af144 Mon Sep 17 00:00:00 2001 From: James O'Toole Date: Wed, 17 Jun 2015 15:24:10 +0100 Subject: [PATCH 6/8] Fixed broken link to documentation Typo "ttp://api..." > "https://api..." --- _layouts/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_layouts/index.html b/_layouts/index.html index 13fcd884..874cad2a 100644 --- a/_layouts/index.html +++ b/_layouts/index.html @@ -24,7 +24,7 @@

{{ site.github.project_title }}

{{ site.github.project_tagline }}