blob: e270c3d027c0f178869c12d68e0cc608a50cca5e [file] [log] [blame]
#!/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