| #!/usr/bin/python |
| # |
| # Copyright 2009 Google Inc. All Rights Reserved. |
| # |
| # 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. |
| |
| """Data model classes for parsing and generating XML for the DocList Data API""" |
| |
| __author__ = 'e.bidelman (Eric Bidelman)' |
| |
| |
| import re |
| import atom.core |
| import atom.data |
| import gdata.acl.data |
| import gdata.data |
| |
| DOCUMENTS_NS = 'http://schemas.google.com/docs/2007' |
| DOCUMENTS_TEMPLATE = '{http://schemas.google.com/docs/2007}%s' |
| ACL_FEEDLINK_REL = 'http://schemas.google.com/acl/2007#accessControlList' |
| REVISION_FEEDLINK_REL = DOCUMENTS_NS + '/revisions' |
| |
| # XML Namespaces used in Google Documents entities. |
| DATA_KIND_SCHEME = 'http://schemas.google.com/g/2005#kind' |
| DOCUMENT_LABEL = 'document' |
| SPREADSHEET_LABEL = 'spreadsheet' |
| PRESENTATION_LABEL = 'presentation' |
| FOLDER_LABEL = 'folder' |
| PDF_LABEL = 'pdf' |
| |
| LABEL_SCHEME = 'http://schemas.google.com/g/2005/labels' |
| STARRED_LABEL_TERM = LABEL_SCHEME + '#starred' |
| TRASHED_LABEL_TERM = LABEL_SCHEME + '#trashed' |
| HIDDEN_LABEL_TERM = LABEL_SCHEME + '#hidden' |
| MINE_LABEL_TERM = LABEL_SCHEME + '#mine' |
| PRIVATE_LABEL_TERM = LABEL_SCHEME + '#private' |
| SHARED_WITH_DOMAIN_LABEL_TERM = LABEL_SCHEME + '#shared-with-domain' |
| VIEWED_LABEL_TERM = LABEL_SCHEME + '#viewed' |
| |
| DOCS_PARENT_LINK_REL = DOCUMENTS_NS + '#parent' |
| DOCS_PUBLISH_LINK_REL = DOCUMENTS_NS + '#publish' |
| |
| FILE_EXT_PATTERN = re.compile('.*\.([a-zA-Z]{3,}$)') |
| RESOURCE_ID_PATTERN = re.compile('^([a-z]*)(:|%3A)([\w-]*)$') |
| |
| # File extension/mimetype pairs of common format. |
| MIMETYPES = { |
| 'CSV': 'text/csv', |
| 'TSV': 'text/tab-separated-values', |
| 'TAB': 'text/tab-separated-values', |
| 'DOC': 'application/msword', |
| 'DOCX': ('application/vnd.openxmlformats-officedocument.' |
| 'wordprocessingml.document'), |
| 'ODS': 'application/x-vnd.oasis.opendocument.spreadsheet', |
| 'ODT': 'application/vnd.oasis.opendocument.text', |
| 'RTF': 'application/rtf', |
| 'SXW': 'application/vnd.sun.xml.writer', |
| 'TXT': 'text/plain', |
| 'XLS': 'application/vnd.ms-excel', |
| 'XLSX': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', |
| 'PDF': 'application/pdf', |
| 'PNG': 'image/png', |
| 'PPT': 'application/vnd.ms-powerpoint', |
| 'PPS': 'application/vnd.ms-powerpoint', |
| 'HTM': 'text/html', |
| 'HTML': 'text/html', |
| 'ZIP': 'application/zip', |
| 'SWF': 'application/x-shockwave-flash' |
| } |
| |
| |
| def make_kind_category(label): |
| """Builds the appropriate atom.data.Category for the label passed in. |
| |
| Args: |
| label: str The value for the category entry. |
| |
| Returns: |
| An atom.data.Category or None if label is None. |
| """ |
| if label is None: |
| return None |
| |
| return atom.data.Category( |
| scheme=DATA_KIND_SCHEME, term='%s#%s' % (DOCUMENTS_NS, label), label=label) |
| |
| MakeKindCategory = make_kind_category |
| |
| def make_content_link_from_resource_id(resource_id): |
| """Constructs export URL for a given resource. |
| |
| Args: |
| resource_id: str The document/item's resource id. Example presentation: |
| 'presentation%3A0A1234567890'. |
| |
| Raises: |
| gdata.client.ValueError if the resource_id is not a valid format. |
| """ |
| match = RESOURCE_ID_PATTERN.match(resource_id) |
| |
| if match: |
| label = match.group(1) |
| doc_id = match.group(3) |
| if label == DOCUMENT_LABEL: |
| return '/feeds/download/documents/Export?docId=%s' % doc_id |
| if label == PRESENTATION_LABEL: |
| return '/feeds/download/presentations/Export?docId=%s' % doc_id |
| if label == SPREADSHEET_LABEL: |
| return ('https://spreadsheets.google.com/feeds/download/spreadsheets/' |
| 'Export?key=%s' % doc_id) |
| raise ValueError, ('Invalid resource id: %s, or manually creating the ' |
| 'download url for this type of doc is not possible' |
| % resource_id) |
| |
| MakeContentLinkFromResourceId = make_content_link_from_resource_id |
| |
| |
| class ResourceId(atom.core.XmlElement): |
| """The DocList gd:resourceId element.""" |
| _qname = gdata.data.GDATA_TEMPLATE % 'resourceId' |
| |
| |
| class LastModifiedBy(atom.data.Person): |
| """The DocList gd:lastModifiedBy element.""" |
| _qname = gdata.data.GDATA_TEMPLATE % 'lastModifiedBy' |
| |
| |
| class LastViewed(atom.data.Person): |
| """The DocList gd:lastViewed element.""" |
| _qname = gdata.data.GDATA_TEMPLATE % 'lastViewed' |
| |
| |
| class WritersCanInvite(atom.core.XmlElement): |
| """The DocList docs:writersCanInvite element.""" |
| _qname = DOCUMENTS_TEMPLATE % 'writersCanInvite' |
| value = 'value' |
| |
| |
| class QuotaBytesUsed(atom.core.XmlElement): |
| """The DocList gd:quotaBytesUsed element.""" |
| _qname = gdata.data.GDATA_TEMPLATE % 'quotaBytesUsed' |
| |
| |
| class Publish(atom.core.XmlElement): |
| """The DocList docs:publish element.""" |
| _qname = DOCUMENTS_TEMPLATE % 'publish' |
| value = 'value' |
| |
| |
| class PublishAuto(atom.core.XmlElement): |
| """The DocList docs:publishAuto element.""" |
| _qname = DOCUMENTS_TEMPLATE % 'publishAuto' |
| value = 'value' |
| |
| |
| class PublishOutsideDomain(atom.core.XmlElement): |
| """The DocList docs:publishOutsideDomain element.""" |
| _qname = DOCUMENTS_TEMPLATE % 'publishOutsideDomain' |
| value = 'value' |
| |
| |
| class DocsEntry(gdata.data.GDEntry): |
| """A DocList version of an Atom Entry.""" |
| |
| last_viewed = LastViewed |
| last_modified_by = LastModifiedBy |
| resource_id = ResourceId |
| writers_can_invite = WritersCanInvite |
| quota_bytes_used = QuotaBytesUsed |
| feed_link = [gdata.data.FeedLink] |
| |
| def get_document_type(self): |
| """Extracts the type of document this DocsEntry is. |
| |
| This method returns the type of document the DocsEntry represents. Possible |
| values are document, presentation, spreadsheet, folder, or pdf. |
| |
| Returns: |
| A string representing the type of document. |
| """ |
| if self.category: |
| for category in self.category: |
| if category.scheme == DATA_KIND_SCHEME: |
| return category.label |
| else: |
| return None |
| |
| GetDocumentType = get_document_type |
| |
| def get_acl_feed_link(self): |
| """Extracts the DocsEntry's ACL feed <gd:feedLink>. |
| |
| Returns: |
| A gdata.data.FeedLink object. |
| """ |
| for feed_link in self.feed_link: |
| if feed_link.rel == ACL_FEEDLINK_REL: |
| return feed_link |
| return None |
| |
| GetAclFeedLink = get_acl_feed_link |
| |
| def get_revisions_feed_link(self): |
| """Extracts the DocsEntry's revisions feed <gd:feedLink>. |
| |
| Returns: |
| A gdata.data.FeedLink object. |
| """ |
| for feed_link in self.feed_link: |
| if feed_link.rel == REVISION_FEEDLINK_REL: |
| return feed_link |
| return None |
| |
| GetRevisionsFeedLink = get_revisions_feed_link |
| |
| def in_folders(self): |
| """Returns the parents link(s) (folders) of this entry.""" |
| links = [] |
| for link in self.link: |
| if link.rel == DOCS_PARENT_LINK_REL and link.href: |
| links.append(link) |
| return links |
| |
| InFolders = in_folders |
| |
| |
| class Acl(gdata.acl.data.AclEntry): |
| """A document ACL entry.""" |
| |
| |
| class DocList(gdata.data.GDFeed): |
| """The main DocList feed containing a list of Google Documents.""" |
| entry = [DocsEntry] |
| |
| |
| class AclFeed(gdata.acl.data.AclFeed): |
| """A DocList ACL feed.""" |
| entry = [Acl] |
| |
| |
| class Revision(gdata.data.GDEntry): |
| """A document Revision entry.""" |
| publish = Publish |
| publish_auto = PublishAuto |
| publish_outside_domain = PublishOutsideDomain |
| |
| def find_publish_link(self): |
| """Get the link that points to the published document on the web. |
| |
| Returns: |
| A str for the URL in the link with a rel ending in #publish. |
| """ |
| return self.find_url(DOCS_PUBLISH_LINK_REL) |
| |
| FindPublishLink = find_publish_link |
| |
| def get_publish_link(self): |
| """Get the link that points to the published document on the web. |
| |
| Returns: |
| A gdata.data.Link for the link with a rel ending in #publish. |
| """ |
| return self.get_link(DOCS_PUBLISH_LINK_REL) |
| |
| GetPublishLink = get_publish_link |
| |
| |
| class RevisionFeed(gdata.data.GDFeed): |
| """A DocList Revision feed.""" |
| entry = [Revision] |