PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/src/googlecl/docs/__init__.py

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