| #!/usr/bin/env python |
| # |
| # Copyright (C) 2009 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. |
| |
| |
| """Contains a client to communicate with the Google Spreadsheets servers. |
| |
| For documentation on the Spreadsheets API, see: |
| http://code.google.com/apis/spreadsheets/ |
| """ |
| |
| |
| __author__ = 'j.s@google.com (Jeff Scudder)' |
| |
| |
| import gdata.client |
| import gdata.gauth |
| import gdata.spreadsheets.data |
| import atom.data |
| import atom.http_core |
| |
| |
| SPREADSHEETS_URL = ('https://spreadsheets.google.com/feeds/spreadsheets' |
| '/private/full') |
| WORKSHEETS_URL = ('https://spreadsheets.google.com/feeds/worksheets/' |
| '%s/private/full') |
| WORKSHEET_URL = ('https://spreadsheets.google.com/feeds/worksheets/' |
| '%s/private/full/%s') |
| TABLES_URL = 'https://spreadsheets.google.com/feeds/%s/tables' |
| RECORDS_URL = 'https://spreadsheets.google.com/feeds/%s/records/%s' |
| RECORD_URL = 'https://spreadsheets.google.com/feeds/%s/records/%s/%s' |
| |
| |
| class SpreadsheetsClient(gdata.client.GDClient): |
| api_version = '3' |
| auth_service = 'wise' |
| auth_scopes = gdata.gauth.AUTH_SCOPES['wise'] |
| ssl = True |
| |
| def get_spreadsheets(self, auth_token=None, |
| desired_class=gdata.spreadsheets.data.SpreadsheetsFeed, |
| **kwargs): |
| """Obtains a feed with the spreadsheets belonging to the current user. |
| |
| Args: |
| auth_token: An object which sets the Authorization HTTP header in its |
| modify_request method. Recommended classes include |
| gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken |
| among others. Represents the current user. Defaults to None |
| and if None, this method will look for a value in the |
| auth_token member of SpreadsheetsClient. |
| desired_class: class descended from atom.core.XmlElement to which a |
| successful response should be converted. If there is no |
| converter function specified (converter=None) then the |
| desired_class will be used in calling the |
| atom.core.parse function. If neither |
| the desired_class nor the converter is specified, an |
| HTTP reponse object will be returned. Defaults to |
| gdata.spreadsheets.data.SpreadsheetsFeed. |
| """ |
| return self.get_feed(SPREADSHEETS_URL, auth_token=auth_token, |
| desired_class=desired_class, **kwargs) |
| |
| GetSpreadsheets = get_spreadsheets |
| |
| def get_worksheets(self, spreadsheet_key, auth_token=None, |
| desired_class=gdata.spreadsheets.data.WorksheetsFeed, |
| **kwargs): |
| """Finds the worksheets within a given spreadsheet. |
| |
| Args: |
| spreadsheet_key: str, The unique ID of this containing spreadsheet. This |
| can be the ID from the URL or as provided in a |
| Spreadsheet entry. |
| auth_token: An object which sets the Authorization HTTP header in its |
| modify_request method. Recommended classes include |
| gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken |
| among others. Represents the current user. Defaults to None |
| and if None, this method will look for a value in the |
| auth_token member of SpreadsheetsClient. |
| desired_class: class descended from atom.core.XmlElement to which a |
| successful response should be converted. If there is no |
| converter function specified (converter=None) then the |
| desired_class will be used in calling the |
| atom.core.parse function. If neither |
| the desired_class nor the converter is specified, an |
| HTTP reponse object will be returned. Defaults to |
| gdata.spreadsheets.data.WorksheetsFeed. |
| """ |
| return self.get_feed(WORKSHEETS_URL % spreadsheet_key, |
| auth_token=auth_token, desired_class=desired_class, |
| **kwargs) |
| |
| GetWorksheets = get_worksheets |
| |
| def add_worksheet(self, spreadsheet_key, title, rows, cols, |
| auth_token=None, **kwargs): |
| """Creates a new worksheet entry in the spreadsheet. |
| |
| Args: |
| spreadsheet_key: str, The unique ID of this containing spreadsheet. This |
| can be the ID from the URL or as provided in a |
| Spreadsheet entry. |
| title: str, The title to be used in for the worksheet. |
| rows: str or int, The number of rows this worksheet should start with. |
| cols: str or int, The number of columns this worksheet should start with. |
| auth_token: An object which sets the Authorization HTTP header in its |
| modify_request method. Recommended classes include |
| gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken |
| among others. Represents the current user. Defaults to None |
| and if None, this method will look for a value in the |
| auth_token member of SpreadsheetsClient. |
| """ |
| new_worksheet = gdata.spreadsheets.data.WorksheetEntry( |
| title=atom.data.Title(text=title), |
| row_count=gdata.spreadsheets.data.RowCount(text=str(rows)), |
| col_count=gdata.spreadsheets.data.ColCount(text=str(cols))) |
| return self.post(new_worksheet, WORKSHEETS_URL % spreadsheet_key, |
| auth_token=auth_token, **kwargs) |
| |
| AddWorksheet = add_worksheet |
| |
| def get_worksheet(self, spreadsheet_key, worksheet_id, |
| desired_class=gdata.spreadsheets.data.WorksheetEntry, |
| auth_token=None, **kwargs): |
| """Retrieves a single worksheet. |
| |
| Args: |
| spreadsheet_key: str, The unique ID of this containing spreadsheet. This |
| can be the ID from the URL or as provided in a |
| Spreadsheet entry. |
| worksheet_id: str, The unique ID for the worksheet withing the desired |
| spreadsheet. |
| auth_token: An object which sets the Authorization HTTP header in its |
| modify_request method. Recommended classes include |
| gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken |
| among others. Represents the current user. Defaults to None |
| and if None, this method will look for a value in the |
| auth_token member of SpreadsheetsClient. |
| desired_class: class descended from atom.core.XmlElement to which a |
| successful response should be converted. If there is no |
| converter function specified (converter=None) then the |
| desired_class will be used in calling the |
| atom.core.parse function. If neither |
| the desired_class nor the converter is specified, an |
| HTTP reponse object will be returned. Defaults to |
| gdata.spreadsheets.data.WorksheetEntry. |
| |
| """ |
| return self.get_entry(WORKSHEET_URL % (spreadsheet_key, worksheet_id,), |
| auth_token=auth_token, desired_class=desired_class, |
| **kwargs) |
| |
| GetWorksheet = get_worksheet |
| |
| def add_table(self, spreadsheet_key, title, summary, worksheet_name, |
| header_row, num_rows, start_row, insertion_mode, |
| column_headers, auth_token=None, **kwargs): |
| """Creates a new table within the worksheet. |
| |
| Args: |
| spreadsheet_key: str, The unique ID of this containing spreadsheet. This |
| can be the ID from the URL or as provided in a |
| Spreadsheet entry. |
| title: str, The title for the new table within a worksheet. |
| summary: str, A description of the table. |
| worksheet_name: str The name of the worksheet in which this table |
| should live. |
| header_row: int or str, The number of the row in the worksheet which |
| will contain the column names for the data in this table. |
| num_rows: int or str, The number of adjacent rows in this table. |
| start_row: int or str, The number of the row at which the data begins. |
| insertion_mode: str |
| column_headers: dict of strings, maps the column letters (A, B, C) to |
| the desired name which will be viewable in the |
| worksheet. |
| auth_token: An object which sets the Authorization HTTP header in its |
| modify_request method. Recommended classes include |
| gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken |
| among others. Represents the current user. Defaults to None |
| and if None, this method will look for a value in the |
| auth_token member of SpreadsheetsClient. |
| """ |
| data = gdata.spreadsheets.data.Data( |
| insertion_mode=insertion_mode, num_rows=str(num_rows), |
| start_row=str(start_row)) |
| for index, name in column_headers.iteritems(): |
| data.column.append(gdata.spreadsheets.data.Column( |
| index=index, name=name)) |
| new_table = gdata.spreadsheets.data.Table( |
| title=atom.data.Title(text=title), summary=atom.data.Summary(summary), |
| worksheet=gdata.spreadsheets.data.Worksheet(name=worksheet_name), |
| header=gdata.spreadsheets.data.Header(row=str(header_row)), data=data) |
| return self.post(new_table, TABLES_URL % spreadsheet_key, |
| auth_token=auth_token, **kwargs) |
| |
| AddTable = add_table |
| |
| def get_tables(self, spreadsheet_key, |
| desired_class=gdata.spreadsheets.data.TablesFeed, |
| auth_token=None, **kwargs): |
| """Retrieves a feed listing the tables in this spreadsheet. |
| |
| Args: |
| spreadsheet_key: str, The unique ID of this containing spreadsheet. This |
| can be the ID from the URL or as provided in a |
| Spreadsheet entry. |
| desired_class: class descended from atom.core.XmlElement to which a |
| successful response should be converted. If there is no |
| converter function specified (converter=None) then the |
| desired_class will be used in calling the |
| atom.core.parse function. If neither |
| the desired_class nor the converter is specified, an |
| HTTP reponse object will be returned. Defaults to |
| gdata.spreadsheets.data.TablesFeed. |
| auth_token: An object which sets the Authorization HTTP header in its |
| modify_request method. Recommended classes include |
| gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken |
| among others. Represents the current user. Defaults to None |
| and if None, this method will look for a value in the |
| auth_token member of SpreadsheetsClient. |
| """ |
| return self.get_feed(TABLES_URL % spreadsheet_key, |
| desired_class=desired_class, auth_token=auth_token, |
| **kwargs) |
| |
| GetTables = get_tables |
| |
| def add_record(self, spreadsheet_key, table_id, fields, |
| title=None, auth_token=None, **kwargs): |
| """Adds a new row to the table. |
| |
| Args: |
| spreadsheet_key: str, The unique ID of this containing spreadsheet. This |
| can be the ID from the URL or as provided in a |
| Spreadsheet entry. |
| table_id: str, The ID of the table within the worksheet which should |
| receive this new record. The table ID can be found using the |
| get_table_id method of a gdata.spreadsheets.data.Table. |
| fields: dict of strings mapping column names to values. |
| title: str, optional The title for this row. |
| auth_token: An object which sets the Authorization HTTP header in its |
| modify_request method. Recommended classes include |
| gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken |
| among others. Represents the current user. Defaults to None |
| and if None, this method will look for a value in the |
| auth_token member of SpreadsheetsClient. |
| """ |
| new_record = gdata.spreadsheets.data.Record() |
| if title is not None: |
| new_record.title = atom.data.Title(text=title) |
| for name, value in fields.iteritems(): |
| new_record.field.append(gdata.spreadsheets.data.Field( |
| name=name, text=value)) |
| return self.post(new_record, RECORDS_URL % (spreadsheet_key, table_id), |
| auth_token=auth_token, **kwargs) |
| |
| AddRecord = add_record |
| |
| def get_records(self, spreadsheet_key, table_id, |
| desired_class=gdata.spreadsheets.data.RecordsFeed, |
| auth_token=None, **kwargs): |
| """Retrieves the records in a table. |
| |
| Args: |
| spreadsheet_key: str, The unique ID of this containing spreadsheet. This |
| can be the ID from the URL or as provided in a |
| Spreadsheet entry. |
| table_id: str, The ID of the table within the worksheet whose records |
| we would like to fetch. The table ID can be found using the |
| get_table_id method of a gdata.spreadsheets.data.Table. |
| desired_class: class descended from atom.core.XmlElement to which a |
| successful response should be converted. If there is no |
| converter function specified (converter=None) then the |
| desired_class will be used in calling the |
| atom.core.parse function. If neither |
| the desired_class nor the converter is specified, an |
| HTTP reponse object will be returned. Defaults to |
| gdata.spreadsheets.data.RecordsFeed. |
| auth_token: An object which sets the Authorization HTTP header in its |
| modify_request method. Recommended classes include |
| gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken |
| among others. Represents the current user. Defaults to None |
| and if None, this method will look for a value in the |
| auth_token member of SpreadsheetsClient. |
| """ |
| return self.get_feed(RECORDS_URL % (spreadsheet_key, table_id), |
| desired_class=desired_class, auth_token=auth_token, |
| **kwargs) |
| |
| GetRecords = get_records |
| |
| def get_record(self, spreadsheet_key, table_id, record_id, |
| desired_class=gdata.spreadsheets.data.Record, |
| auth_token=None, **kwargs): |
| """Retrieves a single record from the table. |
| |
| Args: |
| spreadsheet_key: str, The unique ID of this containing spreadsheet. This |
| can be the ID from the URL or as provided in a |
| Spreadsheet entry. |
| table_id: str, The ID of the table within the worksheet whose records |
| we would like to fetch. The table ID can be found using the |
| get_table_id method of a gdata.spreadsheets.data.Table. |
| record_id: str, The ID of the record within this table which we want to |
| fetch. You can find the record ID using get_record_id() on |
| an instance of the gdata.spreadsheets.data.Record class. |
| desired_class: class descended from atom.core.XmlElement to which a |
| successful response should be converted. If there is no |
| converter function specified (converter=None) then the |
| desired_class will be used in calling the |
| atom.core.parse function. If neither |
| the desired_class nor the converter is specified, an |
| HTTP reponse object will be returned. Defaults to |
| gdata.spreadsheets.data.RecordsFeed. |
| auth_token: An object which sets the Authorization HTTP header in its |
| modify_request method. Recommended classes include |
| gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken |
| among others. Represents the current user. Defaults to None |
| and if None, this method will look for a value in the |
| auth_token member of SpreadsheetsClient.""" |
| return self.get_entry(RECORD_URL % (spreadsheet_key, table_id, record_id), |
| desired_class=desired_class, auth_token=auth_token, |
| **kwargs) |
| |
| GetRecord = get_record |
| |
| |
| class SpreadsheetQuery(gdata.client.Query): |
| |
| def __init__(self, title=None, title_exact=None, **kwargs): |
| """Adds Spreadsheets feed query parameters to a request. |
| |
| Args: |
| title: str Specifies the search terms for the title of a document. |
| This parameter used without title-exact will only submit partial |
| queries, not exact queries. |
| title_exact: str Specifies whether the title query should be taken as an |
| exact string. Meaningless without title. Possible values are |
| 'true' and 'false'. |
| """ |
| gdata.client.Query.__init__(self, **kwargs) |
| self.title = title |
| self.title_exact = title_exact |
| |
| def modify_request(self, http_request): |
| gdata.client._add_query_param('title', self.title, http_request) |
| gdata.client._add_query_param('title-exact', self.title_exact, |
| http_request) |
| gdata.client.Query.modify_request(self, http_request) |
| |
| ModifyRequest = modify_request |
| |
| |
| class WorksheetQuery(SpreadsheetQuery): |
| pass |
| |
| |
| class ListQuery(gdata.client.Query): |
| |
| def __init__(self, order_by=None, reverse=None, sq=None, **kwargs): |
| """Adds List-feed specific query parameters to a request. |
| |
| Args: |
| order_by: str Specifies what column to use in ordering the entries in |
| the feed. By position (the default): 'position' returns |
| rows in the order in which they appear in the GUI. Row 1, then |
| row 2, then row 3, and so on. By column: |
| 'column:columnName' sorts rows in ascending order based on the |
| values in the column with the given columnName, where |
| columnName is the value in the header row for that column. |
| reverse: str Specifies whether to sort in descending or ascending order. |
| Reverses default sort order: 'true' results in a descending |
| sort; 'false' (the default) results in an ascending sort. |
| sq: str Structured query on the full text in the worksheet. |
| [columnName][binaryOperator][value] |
| Supported binaryOperators are: |
| - (), for overriding order of operations |
| - = or ==, for strict equality |
| - <> or !=, for strict inequality |
| - and or &&, for boolean and |
| - or or ||, for boolean or |
| """ |
| gdata.client.Query.__init__(self, **kwargs) |
| self.order_by = order_by |
| self.reverse = reverse |
| self.sq = sq |
| |
| def modify_request(self, http_request): |
| gdata.client._add_query_param('orderby', self.order_by, http_request) |
| gdata.client._add_query_param('reverse', self.reverse, http_request) |
| gdata.client._add_query_param('sq', self.sq, http_request) |
| gdata.client.Query.modify_request(self, http_request) |
| |
| ModifyRequest = modify_request |
| |
| |
| class TableQuery(ListQuery): |
| pass |
| |
| |
| class CellQuery(gdata.client.Query): |
| |
| def __init__(self, min_row=None, max_row=None, min_col=None, max_col=None, |
| range=None, return_empty=None, **kwargs): |
| """Adds Cells-feed specific query parameters to a request. |
| |
| Args: |
| min_row: str or int Positional number of minimum row returned in query. |
| max_row: str or int Positional number of maximum row returned in query. |
| min_col: str or int Positional number of minimum column returned in query. |
| max_col: str or int Positional number of maximum column returned in query. |
| range: str A single cell or a range of cells. Use standard spreadsheet |
| cell-range notations, using a colon to separate start and end of |
| range. Examples: |
| - 'A1' and 'R1C1' both specify only cell A1. |
| - 'D1:F3' and 'R1C4:R3C6' both specify the rectangle of cells with |
| corners at D1 and F3. |
| return_empty: str If 'true' then empty cells will be returned in the feed. |
| If omitted, the default is 'false'. |
| """ |
| gdata.client.Query.__init__(self, **kwargs) |
| self.min_row = min_row |
| self.max_row = max_row |
| self.min_col = min_col |
| self.max_col = max_col |
| self.range = range |
| self.return_empty = return_empty |
| |
| def modify_request(self, http_request): |
| gdata.client._add_query_param('min-row', self.min_row, http_request) |
| gdata.client._add_query_param('max-row', self.max_row, http_request) |
| gdata.client._add_query_param('min-col', self.min_col, http_request) |
| gdata.client._add_query_param('max-col', self.max_col, http_request) |
| gdata.client._add_query_param('range', self.range, http_request) |
| gdata.client._add_query_param('return-empty', self.return_empty, |
| http_request) |
| gdata.client.Query.modify_request(self, http_request) |
| |
| ModifyRequest = modify_request |