Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion bigcommerce/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ def __init__(self, client_id, store_hash, access_token=None, host='api.bigcommer
self.rate_limit = {}

def full_path(self, url):
return "https://" + self.host + self.api_path.format(self.store_hash, url)
if url and isinstance(url, str) and url.startswith('v3/'):
return "https://" + self.host + "/stores/{}/".format(self.store_hash) + url
return "https://" + self.host + self.api_path.format(self.store_hash, url)

@staticmethod
def _oauth_headers(cid, atoken):
Expand Down
54 changes: 54 additions & 0 deletions bigcommerce/resources/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ def videos(self, id=None):
def google_mappings(self):
return GoogleProductSearchMappings.all(self.id, connection=self._connection)

def variants(self, id=None):
if id:
return ProductVariants.get(self.id, id, connection=self._connection)
else:
return ProductVariants.all(self.id, connection=self._connection)

class ProductConfigurableFields(ListableApiSubResource, DeleteableApiSubResource,
CollectionDeleteableApiSubResource, CountableApiSubResource):
Expand Down Expand Up @@ -145,3 +150,52 @@ class GoogleProductSearchMappings(ListableApiSubResource):
resource_name = 'googleproductsearch'
parent_resource = 'products'
parent_key = 'product_id'


class ProductVariants(ApiSubResource):
"""
v3 Catalog variants resource
Endpoints:
- GET /v3/catalog/products/{product_id}/variants
- GET /v3/catalog/products/{product_id}/variants/{variant_id}
- POST /v3/catalog/products/{product_id}/variants
- PUT /v3/catalog/products/{product_id}/variants/{variant_id}
- DELETE /v3/catalog/products/{product_id}/variants/{variant_id}
Responses are wrapped in {'data': ...}; unwrap for callers.
"""

parent_key = 'product_id'

@classmethod
def _v3_path(cls, parentid, id=None):
base = "v3/catalog/products/{}/variants".format(parentid)
return base if id is None else base + "/{}".format(id)

@classmethod
def all(cls, parentid, connection=None, **params):
rsp = cls._make_request('GET', cls._v3_path(parentid), connection, params=params)
items = (rsp or {}).get('data', []) if isinstance(rsp, dict) else (rsp or [])
return [cls(obj, _connection=connection) for obj in items]

@classmethod
def get(cls, parentid, id, connection=None, **params):
rsp = cls._make_request('GET', cls._v3_path(parentid, id), connection, params=params)
data = rsp.get('data', rsp) if isinstance(rsp, dict) else rsp
return cls(data, _connection=connection)

@classmethod
def create(cls, parentid, connection=None, **params):
rsp = cls._make_request('POST', cls._v3_path(parentid), connection, data=params)
data = rsp.get('data', rsp) if isinstance(rsp, dict) else rsp
return cls(data, _connection=connection)

def _update_path_v3(self):
return self._v3_path(self.parent_id(), self.id)

def update(self, **updates):
rsp = self._make_request('PUT', self._update_path_v3(), self._connection, data=updates)
data = rsp.get('data', rsp) if isinstance(rsp, dict) else rsp
return self.__class__(data, _connection=self._connection)

def delete(self):
return self._make_request('DELETE', self._update_path_v3(), self._connection)