| #!/usr/bin/python |
| # |
| # Copyright (C) 2010-2011 Google Inc. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| |
| """Extend the gdata client for the Content API for Shopping. |
| |
| TODO: |
| |
| 1. Proper MCA Support. |
| 2. Better datafeed Support. |
| """ |
| |
| |
| __author__ = 'afshar (Ali Afshar)' |
| |
| |
| import gdata.client |
| import atom.data |
| |
| from gdata.contentforshopping.data import (ProductEntry, ProductFeed, |
| DatafeedFeed, ClientAccountFeed, ClientAccount) |
| |
| |
| CFS_VERSION = 'v1' |
| CFS_HOST = 'content.googleapis.com' |
| CFS_URI = 'https://%s/content' % CFS_HOST |
| CFS_PROJECTION = 'generic' |
| |
| |
| class ContentForShoppingClient(gdata.client.GDClient): |
| """Client for Content for Shopping API. |
| |
| :param account_id: Merchant account ID. This value will be used by default |
| for all requests, but may be overridden on a |
| request-by-request basis. |
| :param api_version: The version of the API to target. Default value: 'v1'. |
| :param **kwargs: Pass all addtional keywords to the GDClient constructor. |
| """ |
| |
| api_version = '1.0' |
| |
| def __init__(self, account_id=None, api_version=CFS_VERSION, **kwargs): |
| self.cfs_account_id = account_id |
| self.cfs_api_version = api_version |
| gdata.client.GDClient.__init__(self, **kwargs) |
| |
| def _create_uri(self, account_id, resource, path=(), use_projection=True): |
| """Create a request uri from the given arguments. |
| |
| If arguments are None, use the default client attributes. |
| """ |
| account_id = account_id or self.cfs_account_id |
| if account_id is None: |
| raise ValueError('No Account ID set. ' |
| 'Either set for the client, or per request') |
| segments = [CFS_URI, self.cfs_api_version, account_id, resource] |
| if use_projection: |
| segments.append(CFS_PROJECTION) |
| segments.extend(path) |
| return '/'.join(segments) |
| |
| def _create_product_id(self, id, country, language): |
| return 'online:%s:%s:%s' % (language, country, id) |
| |
| def _create_batch_feed(self, entries, operation, feed=None): |
| if feed is None: |
| feed = ProductFeed() |
| for entry in entries: |
| entry.batch_operation = gdata.data.BatchOperation(type=operation) |
| feed.entry.append(entry) |
| return feed |
| |
| def get_products(self, start_index=None, max_results=None, account_id=None, |
| auth_token=None): |
| """Get a feed of products for the account. |
| |
| :param max_results: The maximum number of results to return (default 25, |
| maximum 250). |
| :param start_index: The starting index of the feed to return (default 1, |
| maximum 10000) |
| :param account_id: The Merchant Center Account ID. If ommitted the default |
| Account ID will be used for this client |
| """ |
| uri = self._create_uri(account_id, 'items/products') |
| return self.get_feed(uri, auth_token=auth_token, |
| desired_class=gdata.contentforshopping.data.ProductFeed) |
| |
| def get_product(self, id, country, language, account_id=None, |
| auth_token=None): |
| """Get a product by id, country and language. |
| |
| :param id: The product ID |
| :param country: The country (target_country) |
| :param language: The language (content_language) |
| """ |
| pid = self._create_product_id(id, country, language) |
| uri = self._create_uri(account_id, 'items/products', [pid]) |
| return self.get_entry(uri, desired_class=ProductEntry, |
| auth_token=auth_token) |
| |
| def insert_product(self, product, account_id=None, auth_token=None): |
| """Create a new product, by posting the product entry feed. |
| |
| :param product: A :class:`gdata.contentforshopping.data.ProductEntry` with |
| the required product data. |
| :param account_id: The Merchant Center Account ID. If ommitted the default |
| Account ID will be used for this client |
| """ |
| uri = self._create_uri(account_id, 'items/products') |
| return self.post(product, uri=uri, auth_token=auth_token) |
| |
| def insert_products(self, products, account_id=None, auth_token=None): |
| """Insert the products using a batch request |
| |
| :param products: A list of product entries |
| """ |
| feed = self._create_batch_feed(products, 'insert') |
| return self.batch(feed) |
| |
| def delete_products(self, products, account_id=None, auth_token=None): |
| """Delete the products using a batch request. |
| |
| :param products: A list of product entries |
| |
| .. note:: Entries must have the atom:id element set. |
| """ |
| feed = self._create_batch_feed(products, 'delete') |
| return self.batch(feed) |
| |
| def update_products(self, products, account_id=None, auth_token=None): |
| """Update the products using a batch request |
| |
| :param products: A list of product entries |
| |
| .. note:: Entries must have the atom:id element set. |
| """ |
| feed = self._create_batch_feed(products, 'update') |
| return self.batch(feed) |
| |
| def batch(self, feed, account_id=None, auth_token=None): |
| """Send a batch request. |
| |
| :param feed: The feed of batch entries to send. |
| :param account_id: The Merchant Center Account ID. If ommitted the default |
| Account ID will be used for this client |
| """ |
| uri = self._create_uri(account_id, 'items/products', ['batch']) |
| return self.post(feed, uri=uri, auth_token=auth_token, |
| desired_class=ProductFeed) |
| |
| def update_product(self, product, account_id=None, |
| auth_token=None): |
| """Update a product, by putting the product entry feed. |
| |
| :param product: A :class:`gdata.contentforshopping.data.ProductEntry` with |
| the required product data. |
| :param account_id: The Merchant Center Account ID. If ommitted the default |
| Account ID will be used for this client |
| """ |
| pid = self._create_product_id(product.id.text, product.target_country.text, |
| product.content_language.text) |
| uri = self._create_uri(account_id, 'items/products', [pid]) |
| return self.update(product, uri=uri, auth_token=auth_token) |
| |
| def get_datafeeds(self, account_id=None): |
| """Get the feed of datafeeds. |
| """ |
| uri = self._create_uri(account_id, 'datafeeds/products', |
| use_projection=False) |
| return self.get_feed(uri, desired_class=DatafeedFeed) |
| |
| def insert_datafeed(self, entry, account_id=None, auth_token=None): |
| """Insert a datafeed. |
| """ |
| uri = self._create_uri(account_id, 'datafeeds/products', |
| use_projection=False) |
| return self.post(entry, uri=uri, auth_token=auth_token) |
| |
| def get_client_accounts(self, account_id=None, auth_token=None): |
| """Get the feed of managed accounts |
| |
| :param account_id: The Merchant Center Account ID. If ommitted the default |
| Account ID will be used for this client |
| """ |
| uri = self._create_uri(account_id, 'managedaccounts/products', |
| use_projection=False) |
| return self.get_feed(uri, desired_class=ClientAccountFeed, |
| auth_token=auth_token) |
| |
| def insert_client_account(self, entry, account_id=None, auth_token=None): |
| """Insert a client account entry |
| |
| :param entry: An entry of type ClientAccount |
| :param account_id: The Merchant Center Account ID. If ommitted the default |
| Account ID will be used for this client |
| """ |
| uri = self._create_uri(account_id, 'managedaccounts/products', |
| use_projection=False) |
| return self.post(entry, uri=uri, auth_token=auth_token) |
| |
| def update_client_account(self, entry, client_account_id, account_id=None, auth_token=None): |
| """Update a client account |
| |
| :param entry: An entry of type ClientAccount to update to |
| :param client_account_id: The client account ID |
| :param account_id: The Merchant Center Account ID. If ommitted the default |
| Account ID will be used for this client |
| """ |
| uri = self._create_uri(account_id, 'managedaccounts/products', |
| [client_account_id], use_projection=False) |
| return self.update(entry, uri=uri, auth_token=auth_token) |
| |
| def delete_client_account(self, client_account_id, account_id=None, |
| auth_token=None): |
| """Delete a client account |
| |
| :param client_account_id: The client account ID |
| :param account_id: The Merchant Center Account ID. If ommitted the default |
| Account ID will be used for this client |
| """ |
| |
| uri = self._create_uri(account_id, 'managedaccounts/products', |
| [client_account_id], use_projection=False) |
| return self.delete(uri, auth_token=auth_token) |