PageRenderTime 110ms CodeModel.GetById 80ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/src/googlecl/docs/__init__.py

http://googlecl.googlecode.com/
Python | 235 lines | 194 code | 10 blank | 31 comment | 8 complexity | 426c7401b8673bf789759993002eddc9 MD5 | raw file
  1# Copyright (C) 2010 Google Inc.
  2#
  3# Licensed under the Apache License, Version 2.0 (the "License");
  4# you may not use this file except in compliance with the License.
  5# You may obtain a copy of the License at
  6#
  7#      http://www.apache.org/licenses/LICENSE-2.0
  8#
  9# Unless required by applicable law or agreed to in writing, software
 10# distributed under the License is distributed on an "AS IS" BASIS,
 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12# See the License for the specific language governing permissions and
 13# limitations under the License.
 14import googlecl
 15import googlecl.base
 16import logging
 17import os
 18
 19# gdata 1.2.4 doesn't have these defined, but uses them along with
 20# a namespace definition.
 21try:
 22  from gdata.docs.data import DOCUMENT_LABEL, SPREADSHEET_LABEL, \
 23                              PRESENTATION_LABEL, FOLDER_LABEL, PDF_LABEL
 24except ImportError:
 25  DOCUMENT_LABEL = 'document'
 26  SPREADSHEET_LABEL = 'spreadsheet'
 27  PRESENTATION_LABEL = 'presentation'
 28  FOLDER_LABEL = 'folder'
 29  PDF_LABEL = 'pdf'
 30
 31# Drawing label isn't defined even in more recent gdata
 32DRAWING_LABEL = 'drawing'
 33
 34
 35service_name = __name__.split('.')[-1]
 36LOGGER_NAME = __name__
 37SECTION_HEADER = service_name.upper()
 38LOG = logging.getLogger(LOGGER_NAME)
 39
 40
 41def get_document_type(entry):
 42  """Extracts the type of document given DocsEntry is.
 43
 44  This method returns the type of document the DocsEntry represents. Possible
 45  values are document, presentation, spreadsheet, folder, or pdf.
 46  This function appears in gdata-2.x.x python client libraries, and is
 47  copied here for compatibility with gdata-1.2.4.
 48
 49  Returns:
 50    A string representing the type of document.
 51  """
 52  data_kind_scheme = 'http://schemas.google.com/g/2005#kind'
 53  if entry.category:
 54    for category in entry.category:
 55      if category.scheme == data_kind_scheme:
 56        return category.label
 57  else:
 58    return None
 59
 60
 61def get_extension_from_doctype(doctype_label, config_parser):
 62  """Return file extension based on document type and preferences file."""
 63  LOG.debug('In get_extension_from_doctype, doctype_label: ' +
 64             str(doctype_label))
 65  ext = None
 66  if doctype_label == SPREADSHEET_LABEL:
 67    ext = config_parser.safe_get(SECTION_HEADER, 'spreadsheet_format')
 68  elif doctype_label == DOCUMENT_LABEL:
 69    ext = config_parser.safe_get(SECTION_HEADER, 'document_format')
 70  elif doctype_label == PDF_LABEL:
 71    ext = 'pdf'
 72  elif doctype_label == PRESENTATION_LABEL:
 73    ext = config_parser.safe_get(SECTION_HEADER, 'presentation_format')
 74  elif doctype_label == DRAWING_LABEL:
 75    ext = config_parser.safe_get(SECTION_HEADER, 'drawing_format')
 76  elif doctype_label is not None:
 77    LOG.error('Unknown document type label: %s' % doctype_label)
 78  if not ext:
 79    ext = config_parser.safe_get(SECTION_HEADER, 'format')
 80  return ext
 81
 82
 83def get_editor(doctype_label, config_parser):
 84  """Return editor for file based on entry type and preferences file.
 85
 86  Editor is determined in an order of preference:
 87  1) Try to load the editor for the specific type (spreadsheet, document, etc.)
 88  2) If no specification, try to load the "editor" option from config file.
 89  3) If no default editor, try to load the EDITOR environment variable.
 90  4) If no EDITOR variable, return None.
 91
 92  Keyword arguments:
 93    doctype_label: A string representing the type of document to edit.
 94
 95  Returns:
 96    Editor to use to edit the document.
 97  """
 98  LOG.debug('In get_editor, doctype_label: ' + str(doctype_label))
 99  editor = None
100  if doctype_label == SPREADSHEET_LABEL:
101    editor = config_parser.safe_get(SECTION_HEADER, 'spreadsheet_editor')
102  elif doctype_label == DOCUMENT_LABEL:
103    editor = config_parser.safe_get(SECTION_HEADER, 'document_editor')
104  elif doctype_label == PDF_LABEL:
105    editor = config_parser.safe_get(SECTION_HEADER, 'pdf_editor')
106  elif doctype_label == PRESENTATION_LABEL:
107    editor = config_parser.safe_get(SECTION_HEADER, 'presentation_editor')
108  elif doctype_label is not None:
109    LOG.error('Unknown document type label: %s' % doctype_label)
110  if not editor:
111    editor = config_parser.safe_get(SECTION_HEADER, 'editor')
112  if not editor:
113    editor = os.getenv('EDITOR')
114  return editor
115
116
117#===============================================================================
118# Each of the following _run_* functions execute a particular task.
119#
120# Keyword arguments:
121#  client: Client to the service being used.
122#  options: Contains all attributes required to perform the task
123#  args: Additional arguments passed in on the command line, may or may not be
124#        required
125#===============================================================================
126def _run_get(client, options, args):
127  # python gdata 2.0.15 removed Download and added DownloadResource.
128  if not hasattr(client, 'Download') and \
129      not hasattr(client, 'DownloadResource'):
130    LOG.error('Downloading documents is not supported for' +
131              ' gdata-python-client < 2.0')
132    return
133  titles_list = googlecl.build_titles_list(options.title, args)
134  folder_entries = client.get_folder(options.folder)
135  entries = client.get_doclist(titles_list, folder_entries)
136  if not os.path.isdir(options.dest) and len(entries) > 1:
137    LOG.error(googlecl.safe_encode(u'Specified multiple source files, but ' +
138                                   u'destination "' + options.dest +
139                                   u'" is not a directory'))
140    return
141  client.get_docs(options.dest, entries, file_ext=options.format,
142                  grid_id=options.gid)
143
144
145def _run_list(client, options, args):
146  titles_list = googlecl.build_titles_list(options.title, args)
147  folder_entries = client.get_folder(options.folder)
148  entries = client.get_doclist(titles_list, folder_entries)
149  for entry in entries:
150    print googlecl.base.compile_entry_string(
151                               googlecl.base.BaseEntryToStringWrapper(entry),
152                               options.fields.split(','),
153                               delimiter=options.delimiter)
154
155
156def _run_upload(client, options, args):
157  folder_entries = client.get_folder(options.folder)
158  folder_entry = client.get_single_entry(folder_entries)
159  docs_list = options.src + args
160  successful_docs = client.upload_docs(docs_list,
161                                       title=options.title,
162                                       folder_entry=folder_entry,
163                                       file_ext=options.format,
164                                       convert=options.convert)
165
166
167def _run_edit(client, options, args):
168  if args:
169    LOG.info('Sorry, no support for additional arguments for '
170             '"docs edit" yet')
171    LOG.debug('(Ignoring ' + unicode(args) +')')
172
173  # python gdata 2.0.15 removed Download and added DownloadResource.
174  if not hasattr(client, 'Download') and \
175      not hasattr(client, 'DownloadResource'):
176    LOG.error('Editing documents is not supported' +
177              ' for gdata-python-client < 2.0')
178    return
179  folder_entry_list = client.get_folder(options.folder)
180  doc_entry = client.get_single_doc(options.title, folder_entry_list)
181  if doc_entry:
182    doc_entry_or_title = doc_entry
183    doc_type = get_document_type(doc_entry)
184  else:
185    doc_entry_or_title = options.title
186    doc_type = None
187    LOG.debug('No matching documents found! Will create one.')
188  folder_entry = client.get_single_entry(folder_entry_list)
189  if not folder_entry and options.folder:
190    # Don't tell the user no matching folders were found if they didn't
191    # specify one.
192    LOG.debug('No matching folders found! Will create them.')
193  format_ext = options.format or \
194               get_extension_from_doctype(doc_type, client.config)
195  editor = options.editor or get_editor(doc_type, client.config)
196  if not editor:
197    LOG.error('No editor defined!')
198    LOG.info('Define an "editor" option in your config file, set the ' +
199             'EDITOR environment variable, or pass an editor in with --editor.')
200    return
201  if not format_ext:
202    LOG.error('No format defined!')
203    LOG.info('Define a "format" option in your config file,' +
204             ' or pass in a format with --format')
205    return
206  doc = client.edit_doc(doc_entry_or_title, editor, format_ext,
207                        folder_entry_or_path=folder_entry or options.folder)
208  if doc is not None:
209    LOG.info('Document successfully edited! %s', doc.GetHtmlLink().href)
210
211
212def _run_delete(client, options, args):
213  titles_list = googlecl.build_titles_list(options.title, args)
214  folder_entries = client.get_folder(options.folder)
215  entries = client.get_doclist(titles_list, folder_entries)
216  client.DeleteEntryList(entries, 'document', options.prompt)
217
218
219TASKS = {'upload': googlecl.base.Task('Upload a document',
220                                      callback=_run_upload,
221                                      required='src',
222                                      optional=['title', 'folder', 'format']),
223         'edit': googlecl.base.Task('Edit a document', callback=_run_edit,
224                                    required=['title'],
225                                    optional=['format', 'editor', 'folder']),
226         'get': googlecl.base.Task('Download a document', callback=_run_get,
227                                   required=[['title', 'folder'], 'dest'],
228                                   optional='format'),
229         'list': googlecl.base.Task('List documents', callback=_run_list,
230                                    required=['fields', 'delimiter'],
231                                    optional=['title', 'folder']),
232         'delete': googlecl.base.Task('Delete documents',
233                                      callback=_run_delete,
234                                      required='title',
235                                      optional='folder')}