/gdata/docs/data.py

http://radioappz.googlecode.com/ · Python · 280 lines · 218 code · 17 blank · 45 comment · 4 complexity · 3d461b5ff8bc78098a0a2ac803826b21 MD5 · raw file

  1. #!/usr/bin/python
  2. #
  3. # Copyright 2009 Google Inc. All Rights Reserved.
  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. """Data model classes for parsing and generating XML for the DocList Data API"""
  17. __author__ = 'e.bidelman (Eric Bidelman)'
  18. import re
  19. import atom.core
  20. import atom.data
  21. import gdata.acl.data
  22. import gdata.data
  23. DOCUMENTS_NS = 'http://schemas.google.com/docs/2007'
  24. DOCUMENTS_TEMPLATE = '{http://schemas.google.com/docs/2007}%s'
  25. ACL_FEEDLINK_REL = 'http://schemas.google.com/acl/2007#accessControlList'
  26. REVISION_FEEDLINK_REL = DOCUMENTS_NS + '/revisions'
  27. # XML Namespaces used in Google Documents entities.
  28. DATA_KIND_SCHEME = 'http://schemas.google.com/g/2005#kind'
  29. DOCUMENT_LABEL = 'document'
  30. SPREADSHEET_LABEL = 'spreadsheet'
  31. PRESENTATION_LABEL = 'presentation'
  32. FOLDER_LABEL = 'folder'
  33. PDF_LABEL = 'pdf'
  34. LABEL_SCHEME = 'http://schemas.google.com/g/2005/labels'
  35. STARRED_LABEL_TERM = LABEL_SCHEME + '#starred'
  36. TRASHED_LABEL_TERM = LABEL_SCHEME + '#trashed'
  37. HIDDEN_LABEL_TERM = LABEL_SCHEME + '#hidden'
  38. MINE_LABEL_TERM = LABEL_SCHEME + '#mine'
  39. PRIVATE_LABEL_TERM = LABEL_SCHEME + '#private'
  40. SHARED_WITH_DOMAIN_LABEL_TERM = LABEL_SCHEME + '#shared-with-domain'
  41. VIEWED_LABEL_TERM = LABEL_SCHEME + '#viewed'
  42. DOCS_PARENT_LINK_REL = DOCUMENTS_NS + '#parent'
  43. DOCS_PUBLISH_LINK_REL = DOCUMENTS_NS + '#publish'
  44. FILE_EXT_PATTERN = re.compile('.*\.([a-zA-Z]{3,}$)')
  45. RESOURCE_ID_PATTERN = re.compile('^([a-z]*)(:|%3A)([\w-]*)$')
  46. # File extension/mimetype pairs of common format.
  47. MIMETYPES = {
  48. 'CSV': 'text/csv',
  49. 'TSV': 'text/tab-separated-values',
  50. 'TAB': 'text/tab-separated-values',
  51. 'DOC': 'application/msword',
  52. 'DOCX': ('application/vnd.openxmlformats-officedocument.'
  53. 'wordprocessingml.document'),
  54. 'ODS': 'application/x-vnd.oasis.opendocument.spreadsheet',
  55. 'ODT': 'application/vnd.oasis.opendocument.text',
  56. 'RTF': 'application/rtf',
  57. 'SXW': 'application/vnd.sun.xml.writer',
  58. 'TXT': 'text/plain',
  59. 'XLS': 'application/vnd.ms-excel',
  60. 'XLSX': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  61. 'PDF': 'application/pdf',
  62. 'PNG': 'image/png',
  63. 'PPT': 'application/vnd.ms-powerpoint',
  64. 'PPS': 'application/vnd.ms-powerpoint',
  65. 'HTM': 'text/html',
  66. 'HTML': 'text/html',
  67. 'ZIP': 'application/zip',
  68. 'SWF': 'application/x-shockwave-flash'
  69. }
  70. def make_kind_category(label):
  71. """Builds the appropriate atom.data.Category for the label passed in.
  72. Args:
  73. label: str The value for the category entry.
  74. Returns:
  75. An atom.data.Category or None if label is None.
  76. """
  77. if label is None:
  78. return None
  79. return atom.data.Category(
  80. scheme=DATA_KIND_SCHEME, term='%s#%s' % (DOCUMENTS_NS, label), label=label)
  81. MakeKindCategory = make_kind_category
  82. def make_content_link_from_resource_id(resource_id):
  83. """Constructs export URL for a given resource.
  84. Args:
  85. resource_id: str The document/item's resource id. Example presentation:
  86. 'presentation%3A0A1234567890'.
  87. Raises:
  88. gdata.client.ValueError if the resource_id is not a valid format.
  89. """
  90. match = RESOURCE_ID_PATTERN.match(resource_id)
  91. if match:
  92. label = match.group(1)
  93. doc_id = match.group(3)
  94. if label == DOCUMENT_LABEL:
  95. return '/feeds/download/documents/Export?docId=%s' % doc_id
  96. if label == PRESENTATION_LABEL:
  97. return '/feeds/download/presentations/Export?docId=%s' % doc_id
  98. if label == SPREADSHEET_LABEL:
  99. return ('http://spreadsheets.google.com/feeds/download/spreadsheets/'
  100. 'Export?key=%s' % doc_id)
  101. raise ValueError, ('Invalid resource id: %s, or manually creating the '
  102. 'download url for this type of doc is not possible'
  103. % resource_id)
  104. MakeContentLinkFromResourceId = make_content_link_from_resource_id
  105. class ResourceId(atom.core.XmlElement):
  106. """The DocList gd:resourceId element."""
  107. _qname = gdata.data.GDATA_TEMPLATE % 'resourceId'
  108. class LastModifiedBy(atom.data.Person):
  109. """The DocList gd:lastModifiedBy element."""
  110. _qname = gdata.data.GDATA_TEMPLATE % 'lastModifiedBy'
  111. class LastViewed(atom.data.Person):
  112. """The DocList gd:lastViewed element."""
  113. _qname = gdata.data.GDATA_TEMPLATE % 'lastViewed'
  114. class WritersCanInvite(atom.core.XmlElement):
  115. """The DocList docs:writersCanInvite element."""
  116. _qname = DOCUMENTS_TEMPLATE % 'writersCanInvite'
  117. value = 'value'
  118. class QuotaBytesUsed(atom.core.XmlElement):
  119. """The DocList gd:quotaBytesUsed element."""
  120. _qname = gdata.data.GDATA_TEMPLATE % 'quotaBytesUsed'
  121. class Publish(atom.core.XmlElement):
  122. """The DocList docs:publish element."""
  123. _qname = DOCUMENTS_TEMPLATE % 'publish'
  124. value = 'value'
  125. class PublishAuto(atom.core.XmlElement):
  126. """The DocList docs:publishAuto element."""
  127. _qname = DOCUMENTS_TEMPLATE % 'publishAuto'
  128. value = 'value'
  129. class PublishOutsideDomain(atom.core.XmlElement):
  130. """The DocList docs:publishOutsideDomain element."""
  131. _qname = DOCUMENTS_TEMPLATE % 'publishOutsideDomain'
  132. value = 'value'
  133. class DocsEntry(gdata.data.GDEntry):
  134. """A DocList version of an Atom Entry."""
  135. last_viewed = LastViewed
  136. last_modified_by = LastModifiedBy
  137. resource_id = ResourceId
  138. writers_can_invite = WritersCanInvite
  139. quota_bytes_used = QuotaBytesUsed
  140. feed_link = [gdata.data.FeedLink]
  141. def get_document_type(self):
  142. """Extracts the type of document this DocsEntry is.
  143. This method returns the type of document the DocsEntry represents. Possible
  144. values are document, presentation, spreadsheet, folder, or pdf.
  145. Returns:
  146. A string representing the type of document.
  147. """
  148. if self.category:
  149. for category in self.category:
  150. if category.scheme == DATA_KIND_SCHEME:
  151. return category.label
  152. else:
  153. return None
  154. GetDocumentType = get_document_type
  155. def get_acl_feed_link(self):
  156. """Extracts the DocsEntry's ACL feed <gd:feedLink>.
  157. Returns:
  158. A gdata.data.FeedLink object.
  159. """
  160. for feed_link in self.feed_link:
  161. if feed_link.rel == ACL_FEEDLINK_REL:
  162. return feed_link
  163. return None
  164. GetAclFeedLink = get_acl_feed_link
  165. def get_revisions_feed_link(self):
  166. """Extracts the DocsEntry's revisions feed <gd:feedLink>.
  167. Returns:
  168. A gdata.data.FeedLink object.
  169. """
  170. for feed_link in self.feed_link:
  171. if feed_link.rel == REVISION_FEEDLINK_REL:
  172. return feed_link
  173. return None
  174. GetRevisionsFeedLink = get_revisions_feed_link
  175. def in_folders(self):
  176. """Returns the parents link(s) (folders) of this entry."""
  177. links = []
  178. for link in self.link:
  179. if link.rel == DOCS_PARENT_LINK_REL and link.href:
  180. links.append(link)
  181. return links
  182. InFolders = in_folders
  183. class Acl(gdata.acl.data.AclEntry):
  184. """A document ACL entry."""
  185. class DocList(gdata.data.GDFeed):
  186. """The main DocList feed containing a list of Google Documents."""
  187. entry = [DocsEntry]
  188. class AclFeed(gdata.acl.data.AclFeed):
  189. """A DocList ACL feed."""
  190. entry = [Acl]
  191. class Revision(gdata.data.GDEntry):
  192. """A document Revision entry."""
  193. publish = Publish
  194. publish_auto = PublishAuto
  195. publish_outside_domain = PublishOutsideDomain
  196. def find_publish_link(self):
  197. """Get the link that points to the published document on the web.
  198. Returns:
  199. A str for the URL in the link with a rel ending in #publish.
  200. """
  201. return self.find_url(DOCS_PUBLISH_LINK_REL)
  202. FindPublishLink = find_publish_link
  203. def get_publish_link(self):
  204. """Get the link that points to the published document on the web.
  205. Returns:
  206. A gdata.data.Link for the link with a rel ending in #publish.
  207. """
  208. return self.get_link(DOCS_PUBLISH_LINK_REL)
  209. GetPublishLink = get_publish_link
  210. class RevisionFeed(gdata.data.GDFeed):
  211. """A DocList Revision feed."""
  212. entry = [Revision]