/gdata/spreadsheets/client.py
Python | 451 lines | 199 code | 31 blank | 221 comment | 6 complexity | 987009f85fab2b3fc52867601296bada MD5 | raw file
1#!/usr/bin/env python 2# 3# Copyright (C) 2009 Google Inc. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17 18"""Contains a client to communicate with the Google Spreadsheets servers. 19 20For documentation on the Spreadsheets API, see: 21http://code.google.com/apis/spreadsheets/ 22""" 23 24 25__author__ = 'j.s@google.com (Jeff Scudder)' 26 27 28import gdata.client 29import gdata.gauth 30import gdata.spreadsheets.data 31import atom.data 32import atom.http_core 33 34 35SPREADSHEETS_URL = ('http://spreadsheets.google.com/feeds/spreadsheets' 36 '/private/full') 37WORKSHEETS_URL = ('http://spreadsheets.google.com/feeds/worksheets/' 38 '%s/private/full') 39WORKSHEET_URL = ('http://spreadsheets.google.com/feeds/worksheets/' 40 '%s/private/full/%s') 41TABLES_URL = 'http://spreadsheets.google.com/feeds/%s/tables' 42RECORDS_URL = 'http://spreadsheets.google.com/feeds/%s/records/%s' 43RECORD_URL = 'http://spreadsheets.google.com/feeds/%s/records/%s/%s' 44 45 46class SpreadsheetsClient(gdata.client.GDClient): 47 api_version = '3' 48 auth_service = 'wise' 49 auth_scopes = gdata.gauth.AUTH_SCOPES['wise'] 50 51 def get_spreadsheets(self, auth_token=None, 52 desired_class=gdata.spreadsheets.data.SpreadsheetsFeed, 53 **kwargs): 54 """Obtains a feed with the spreadsheets belonging to the current user. 55 56 Args: 57 auth_token: An object which sets the Authorization HTTP header in its 58 modify_request method. Recommended classes include 59 gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken 60 among others. Represents the current user. Defaults to None 61 and if None, this method will look for a value in the 62 auth_token member of SpreadsheetsClient. 63 desired_class: class descended from atom.core.XmlElement to which a 64 successful response should be converted. If there is no 65 converter function specified (converter=None) then the 66 desired_class will be used in calling the 67 atom.core.parse function. If neither 68 the desired_class nor the converter is specified, an 69 HTTP reponse object will be returned. Defaults to 70 gdata.spreadsheets.data.SpreadsheetsFeed. 71 """ 72 return self.get_feed(SPREADSHEETS_URL, auth_token=auth_token, 73 desired_class=desired_class, **kwargs) 74 75 GetSpreadsheets = get_spreadsheets 76 77 def get_worksheets(self, spreadsheet_key, auth_token=None, 78 desired_class=gdata.spreadsheets.data.WorksheetsFeed, 79 **kwargs): 80 """Finds the worksheets within a given spreadsheet. 81 82 Args: 83 spreadsheet_key: str, The unique ID of this containing spreadsheet. This 84 can be the ID from the URL or as provided in a 85 Spreadsheet entry. 86 auth_token: An object which sets the Authorization HTTP header in its 87 modify_request method. Recommended classes include 88 gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken 89 among others. Represents the current user. Defaults to None 90 and if None, this method will look for a value in the 91 auth_token member of SpreadsheetsClient. 92 desired_class: class descended from atom.core.XmlElement to which a 93 successful response should be converted. If there is no 94 converter function specified (converter=None) then the 95 desired_class will be used in calling the 96 atom.core.parse function. If neither 97 the desired_class nor the converter is specified, an 98 HTTP reponse object will be returned. Defaults to 99 gdata.spreadsheets.data.WorksheetsFeed. 100 """ 101 return self.get_feed(WORKSHEETS_URL % spreadsheet_key, 102 auth_token=auth_token, desired_class=desired_class, 103 **kwargs) 104 105 GetWorksheets = get_worksheets 106 107 def add_worksheet(self, spreadsheet_key, title, rows, cols, 108 auth_token=None, **kwargs): 109 """Creates a new worksheet entry in the spreadsheet. 110 111 Args: 112 spreadsheet_key: str, The unique ID of this containing spreadsheet. This 113 can be the ID from the URL or as provided in a 114 Spreadsheet entry. 115 title: str, The title to be used in for the worksheet. 116 rows: str or int, The number of rows this worksheet should start with. 117 cols: str or int, The number of columns this worksheet should start with. 118 auth_token: An object which sets the Authorization HTTP header in its 119 modify_request method. Recommended classes include 120 gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken 121 among others. Represents the current user. Defaults to None 122 and if None, this method will look for a value in the 123 auth_token member of SpreadsheetsClient. 124 """ 125 new_worksheet = gdata.spreadsheets.data.WorksheetEntry( 126 title=atom.data.Title(text=title), 127 row_count=gdata.spreadsheets.data.RowCount(text=str(rows)), 128 col_count=gdata.spreadsheets.data.ColCount(text=str(cols))) 129 return self.post(new_worksheet, WORKSHEETS_URL % spreadsheet_key, 130 auth_token=auth_token, **kwargs) 131 132 AddWorksheet = add_worksheet 133 134 def get_worksheet(self, spreadsheet_key, worksheet_id, 135 desired_class=gdata.spreadsheets.data.WorksheetEntry, 136 auth_token=None, **kwargs): 137 """Retrieves a single worksheet. 138 139 Args: 140 spreadsheet_key: str, The unique ID of this containing spreadsheet. This 141 can be the ID from the URL or as provided in a 142 Spreadsheet entry. 143 worksheet_id: str, The unique ID for the worksheet withing the desired 144 spreadsheet. 145 auth_token: An object which sets the Authorization HTTP header in its 146 modify_request method. Recommended classes include 147 gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken 148 among others. Represents the current user. Defaults to None 149 and if None, this method will look for a value in the 150 auth_token member of SpreadsheetsClient. 151 desired_class: class descended from atom.core.XmlElement to which a 152 successful response should be converted. If there is no 153 converter function specified (converter=None) then the 154 desired_class will be used in calling the 155 atom.core.parse function. If neither 156 the desired_class nor the converter is specified, an 157 HTTP reponse object will be returned. Defaults to 158 gdata.spreadsheets.data.WorksheetEntry. 159 160 """ 161 return self.get_entry(WORKSHEET_URL % (spreadsheet_key, worksheet_id,), 162 auth_token=auth_token, desired_class=desired_class, 163 **kwargs) 164 165 GetWorksheet = get_worksheet 166 167 def add_table(self, spreadsheet_key, title, summary, worksheet_name, 168 header_row, num_rows, start_row, insertion_mode, 169 column_headers, auth_token=None, **kwargs): 170 """Creates a new table within the worksheet. 171 172 Args: 173 spreadsheet_key: str, The unique ID of this containing spreadsheet. This 174 can be the ID from the URL or as provided in a 175 Spreadsheet entry. 176 title: str, The title for the new table within a worksheet. 177 summary: str, A description of the table. 178 worksheet_name: str The name of the worksheet in which this table 179 should live. 180 header_row: int or str, The number of the row in the worksheet which 181 will contain the column names for the data in this table. 182 num_rows: int or str, The number of adjacent rows in this table. 183 start_row: int or str, The number of the row at which the data begins. 184 insertion_mode: str 185 column_headers: dict of strings, maps the column letters (A, B, C) to 186 the desired name which will be viewable in the 187 worksheet. 188 auth_token: An object which sets the Authorization HTTP header in its 189 modify_request method. Recommended classes include 190 gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken 191 among others. Represents the current user. Defaults to None 192 and if None, this method will look for a value in the 193 auth_token member of SpreadsheetsClient. 194 """ 195 data = gdata.spreadsheets.data.Data( 196 insertion_mode=insertion_mode, num_rows=str(num_rows), 197 start_row=str(start_row)) 198 for index, name in column_headers.iteritems(): 199 data.column.append(gdata.spreadsheets.data.Column( 200 index=index, name=name)) 201 new_table = gdata.spreadsheets.data.Table( 202 title=atom.data.Title(text=title), summary=atom.data.Summary(summary), 203 worksheet=gdata.spreadsheets.data.Worksheet(name=worksheet_name), 204 header=gdata.spreadsheets.data.Header(row=str(header_row)), data=data) 205 return self.post(new_table, TABLES_URL % spreadsheet_key, 206 auth_token=auth_token, **kwargs) 207 208 AddTable = add_table 209 210 def get_tables(self, spreadsheet_key, 211 desired_class=gdata.spreadsheets.data.TablesFeed, 212 auth_token=None, **kwargs): 213 """Retrieves a feed listing the tables in this spreadsheet. 214 215 Args: 216 spreadsheet_key: str, The unique ID of this containing spreadsheet. This 217 can be the ID from the URL or as provided in a 218 Spreadsheet entry. 219 desired_class: class descended from atom.core.XmlElement to which a 220 successful response should be converted. If there is no 221 converter function specified (converter=None) then the 222 desired_class will be used in calling the 223 atom.core.parse function. If neither 224 the desired_class nor the converter is specified, an 225 HTTP reponse object will be returned. Defaults to 226 gdata.spreadsheets.data.TablesFeed. 227 auth_token: An object which sets the Authorization HTTP header in its 228 modify_request method. Recommended classes include 229 gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken 230 among others. Represents the current user. Defaults to None 231 and if None, this method will look for a value in the 232 auth_token member of SpreadsheetsClient. 233 """ 234 return self.get_feed(TABLES_URL % spreadsheet_key, 235 desired_class=desired_class, auth_token=auth_token, 236 **kwargs) 237 238 GetTables = get_tables 239 240 def add_record(self, spreadsheet_key, table_id, fields, 241 title=None, auth_token=None, **kwargs): 242 """Adds a new row to the table. 243 244 Args: 245 spreadsheet_key: str, The unique ID of this containing spreadsheet. This 246 can be the ID from the URL or as provided in a 247 Spreadsheet entry. 248 table_id: str, The ID of the table within the worksheet which should 249 receive this new record. The table ID can be found using the 250 get_table_id method of a gdata.spreadsheets.data.Table. 251 fields: dict of strings mapping column names to values. 252 title: str, optional The title for this row. 253 auth_token: An object which sets the Authorization HTTP header in its 254 modify_request method. Recommended classes include 255 gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken 256 among others. Represents the current user. Defaults to None 257 and if None, this method will look for a value in the 258 auth_token member of SpreadsheetsClient. 259 """ 260 new_record = gdata.spreadsheets.data.Record() 261 if title is not None: 262 new_record.title = atom.data.Title(text=title) 263 for name, value in fields.iteritems(): 264 new_record.field.append(gdata.spreadsheets.data.Field( 265 name=name, text=value)) 266 return self.post(new_record, RECORDS_URL % (spreadsheet_key, table_id), 267 auth_token=auth_token, **kwargs) 268 269 AddRecord = add_record 270 271 def get_records(self, spreadsheet_key, table_id, 272 desired_class=gdata.spreadsheets.data.RecordsFeed, 273 auth_token=None, **kwargs): 274 """Retrieves the records in a table. 275 276 Args: 277 spreadsheet_key: str, The unique ID of this containing spreadsheet. This 278 can be the ID from the URL or as provided in a 279 Spreadsheet entry. 280 table_id: str, The ID of the table within the worksheet whose records 281 we would like to fetch. The table ID can be found using the 282 get_table_id method of a gdata.spreadsheets.data.Table. 283 desired_class: class descended from atom.core.XmlElement to which a 284 successful response should be converted. If there is no 285 converter function specified (converter=None) then the 286 desired_class will be used in calling the 287 atom.core.parse function. If neither 288 the desired_class nor the converter is specified, an 289 HTTP reponse object will be returned. Defaults to 290 gdata.spreadsheets.data.RecordsFeed. 291 auth_token: An object which sets the Authorization HTTP header in its 292 modify_request method. Recommended classes include 293 gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken 294 among others. Represents the current user. Defaults to None 295 and if None, this method will look for a value in the 296 auth_token member of SpreadsheetsClient. 297 """ 298 return self.get_feed(RECORDS_URL % (spreadsheet_key, table_id), 299 desired_class=desired_class, auth_token=auth_token, 300 **kwargs) 301 302 GetRecords = get_records 303 304 def get_record(self, spreadsheet_key, table_id, record_id, 305 desired_class=gdata.spreadsheets.data.Record, 306 auth_token=None, **kwargs): 307 """Retrieves a single record from the table. 308 309 Args: 310 spreadsheet_key: str, The unique ID of this containing spreadsheet. This 311 can be the ID from the URL or as provided in a 312 Spreadsheet entry. 313 table_id: str, The ID of the table within the worksheet whose records 314 we would like to fetch. The table ID can be found using the 315 get_table_id method of a gdata.spreadsheets.data.Table. 316 record_id: str, The ID of the record within this table which we want to 317 fetch. You can find the record ID using get_record_id() on 318 an instance of the gdata.spreadsheets.data.Record class. 319 desired_class: class descended from atom.core.XmlElement to which a 320 successful response should be converted. If there is no 321 converter function specified (converter=None) then the 322 desired_class will be used in calling the 323 atom.core.parse function. If neither 324 the desired_class nor the converter is specified, an 325 HTTP reponse object will be returned. Defaults to 326 gdata.spreadsheets.data.RecordsFeed. 327 auth_token: An object which sets the Authorization HTTP header in its 328 modify_request method. Recommended classes include 329 gdata.gauth.ClientLoginToken and gdata.gauth.AuthSubToken 330 among others. Represents the current user. Defaults to None 331 and if None, this method will look for a value in the 332 auth_token member of SpreadsheetsClient.""" 333 return self.get_entry(RECORD_URL % (spreadsheet_key, table_id, record_id), 334 desired_class=desired_class, auth_token=auth_token, 335 **kwargs) 336 337 GetRecord = get_record 338 339 340class SpreadsheetQuery(gdata.client.Query): 341 342 def __init__(self, title=None, title_exact=None, **kwargs): 343 """Adds Spreadsheets feed query parameters to a request. 344 345 Args: 346 title: str Specifies the search terms for the title of a document. 347 This parameter used without title-exact will only submit partial 348 queries, not exact queries. 349 title_exact: str Specifies whether the title query should be taken as an 350 exact string. Meaningless without title. Possible values are 351 'true' and 'false'. 352 """ 353 gdata.client.Query.__init__(self, **kwargs) 354 self.title = title 355 self.title_exact = title_exact 356 357 def modify_request(self, http_request): 358 gdata.client._add_query_param('title', self.title, http_request) 359 gdata.client._add_query_param('title-exact', self.title_exact, 360 http_request) 361 gdata.client.Query.modify_request(self, http_request) 362 363 ModifyRequest = modify_request 364 365 366class WorksheetQuery(SpreadsheetQuery): 367 pass 368 369 370class ListQuery(gdata.client.Query): 371 372 def __init__(self, order_by=None, reverse=None, sq=None, **kwargs): 373 """Adds List-feed specific query parameters to a request. 374 375 Args: 376 order_by: str Specifies what column to use in ordering the entries in 377 the feed. By position (the default): 'position' returns 378 rows in the order in which they appear in the GUI. Row 1, then 379 row 2, then row 3, and so on. By column: 380 'column:columnName' sorts rows in ascending order based on the 381 values in the column with the given columnName, where 382 columnName is the value in the header row for that column. 383 reverse: str Specifies whether to sort in descending or ascending order. 384 Reverses default sort order: 'true' results in a descending 385 sort; 'false' (the default) results in an ascending sort. 386 sq: str Structured query on the full text in the worksheet. 387 [columnName][binaryOperator][value] 388 Supported binaryOperators are: 389 - (), for overriding order of operations 390 - = or ==, for strict equality 391 - <> or !=, for strict inequality 392 - and or &&, for boolean and 393 - or or ||, for boolean or 394 """ 395 gdata.client.Query.__init__(self, **kwargs) 396 self.order_by = order_by 397 self.reverse = reverse 398 self.sq = sq 399 400 def modify_request(self, http_request): 401 gdata.client._add_query_param('orderby', self.order_by, http_request) 402 gdata.client._add_query_param('reverse', self.reverse, http_request) 403 gdata.client._add_query_param('sq', self.sq, http_request) 404 gdata.client.Query.modify_request(self, http_request) 405 406 ModifyRequest = modify_request 407 408 409class TableQuery(ListQuery): 410 pass 411 412 413class CellQuery(gdata.client.Query): 414 415 def __init__(self, min_row=None, max_row=None, min_col=None, max_col=None, 416 range=None, return_empty=None, **kwargs): 417 """Adds Cells-feed specific query parameters to a request. 418 419 Args: 420 min_row: str or int Positional number of minimum row returned in query. 421 max_row: str or int Positional number of maximum row returned in query. 422 min_col: str or int Positional number of minimum column returned in query. 423 max_col: str or int Positional number of maximum column returned in query. 424 range: str A single cell or a range of cells. Use standard spreadsheet 425 cell-range notations, using a colon to separate start and end of 426 range. Examples: 427 - 'A1' and 'R1C1' both specify only cell A1. 428 - 'D1:F3' and 'R1C4:R3C6' both specify the rectangle of cells with 429 corners at D1 and F3. 430 return_empty: str If 'true' then empty cells will be returned in the feed. 431 If omitted, the default is 'false'. 432 """ 433 gdata.client.Query.__init__(self, **kwargs) 434 self.min_row = min_row 435 self.max_row = max_row 436 self.min_col = min_col 437 self.max_col = max_col 438 self.range = range 439 self.return_empty = return_empty 440 441 def modify_request(self, http_request): 442 gdata.client._add_query_param('min-row', self.min_row, http_request) 443 gdata.client._add_query_param('max-row', self.max_row, http_request) 444 gdata.client._add_query_param('min-col', self.min_col, http_request) 445 gdata.client._add_query_param('max-col', self.max_col, http_request) 446 gdata.client._add_query_param('range', self.range, http_request) 447 gdata.client._add_query_param('return-empty', self.return_empty, 448 http_request) 449 gdata.client.Query.modify_request(self, http_request) 450 451 ModifyRequest = modify_request