/gdata/data.py
http://radioappz.googlecode.com/ · Python · 1186 lines · 954 code · 105 blank · 127 comment · 40 complexity · 37c107a6020c086c65bf681496e76015 MD5 · raw file
- #!/usr/bin/env python
- #
- # Copyright (C) 2009 Google Inc.
- #
- # 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.
- # This module is used for version 2 of the Google Data APIs.
- """Provides classes and constants for the XML in the Google Data namespace.
- Documentation for the raw XML which these classes represent can be found here:
- http://code.google.com/apis/gdata/docs/2.0/elements.html
- """
- __author__ = 'j.s@google.com (Jeff Scudder)'
- import os
- import atom.core
- import atom.data
- GDATA_TEMPLATE = '{http://schemas.google.com/g/2005}%s'
- GD_TEMPLATE = GDATA_TEMPLATE
- OPENSEARCH_TEMPLATE_V1 = '{http://a9.com/-/spec/opensearchrss/1.0/}%s'
- OPENSEARCH_TEMPLATE_V2 = '{http://a9.com/-/spec/opensearch/1.1/}%s'
- BATCH_TEMPLATE = '{http://schemas.google.com/gdata/batch}%s'
- # Labels used in batch request entries to specify the desired CRUD operation.
- BATCH_INSERT = 'insert'
- BATCH_UPDATE = 'update'
- BATCH_DELETE = 'delete'
- BATCH_QUERY = 'query'
- EVENT_LOCATION = 'http://schemas.google.com/g/2005#event'
- ALTERNATE_LOCATION = 'http://schemas.google.com/g/2005#event.alternate'
- PARKING_LOCATION = 'http://schemas.google.com/g/2005#event.parking'
- CANCELED_EVENT = 'http://schemas.google.com/g/2005#event.canceled'
- CONFIRMED_EVENT = 'http://schemas.google.com/g/2005#event.confirmed'
- TENTATIVE_EVENT = 'http://schemas.google.com/g/2005#event.tentative'
- CONFIDENTIAL_EVENT = 'http://schemas.google.com/g/2005#event.confidential'
- DEFAULT_EVENT = 'http://schemas.google.com/g/2005#event.default'
- PRIVATE_EVENT = 'http://schemas.google.com/g/2005#event.private'
- PUBLIC_EVENT = 'http://schemas.google.com/g/2005#event.public'
- OPAQUE_EVENT = 'http://schemas.google.com/g/2005#event.opaque'
- TRANSPARENT_EVENT = 'http://schemas.google.com/g/2005#event.transparent'
- CHAT_MESSAGE = 'http://schemas.google.com/g/2005#message.chat'
- INBOX_MESSAGE = 'http://schemas.google.com/g/2005#message.inbox'
- SENT_MESSAGE = 'http://schemas.google.com/g/2005#message.sent'
- SPAM_MESSAGE = 'http://schemas.google.com/g/2005#message.spam'
- STARRED_MESSAGE = 'http://schemas.google.com/g/2005#message.starred'
- UNREAD_MESSAGE = 'http://schemas.google.com/g/2005#message.unread'
- BCC_RECIPIENT = 'http://schemas.google.com/g/2005#message.bcc'
- CC_RECIPIENT = 'http://schemas.google.com/g/2005#message.cc'
- SENDER = 'http://schemas.google.com/g/2005#message.from'
- REPLY_TO = 'http://schemas.google.com/g/2005#message.reply-to'
- TO_RECIPIENT = 'http://schemas.google.com/g/2005#message.to'
- ASSISTANT_REL = 'http://schemas.google.com/g/2005#assistant'
- CALLBACK_REL = 'http://schemas.google.com/g/2005#callback'
- CAR_REL = 'http://schemas.google.com/g/2005#car'
- COMPANY_MAIN_REL = 'http://schemas.google.com/g/2005#company_main'
- FAX_REL = 'http://schemas.google.com/g/2005#fax'
- HOME_REL = 'http://schemas.google.com/g/2005#home'
- HOME_FAX_REL = 'http://schemas.google.com/g/2005#home_fax'
- ISDN_REL = 'http://schemas.google.com/g/2005#isdn'
- MAIN_REL = 'http://schemas.google.com/g/2005#main'
- MOBILE_REL = 'http://schemas.google.com/g/2005#mobile'
- OTHER_REL = 'http://schemas.google.com/g/2005#other'
- OTHER_FAX_REL = 'http://schemas.google.com/g/2005#other_fax'
- PAGER_REL = 'http://schemas.google.com/g/2005#pager'
- RADIO_REL = 'http://schemas.google.com/g/2005#radio'
- TELEX_REL = 'http://schemas.google.com/g/2005#telex'
- TTL_TDD_REL = 'http://schemas.google.com/g/2005#tty_tdd'
- WORK_REL = 'http://schemas.google.com/g/2005#work'
- WORK_FAX_REL = 'http://schemas.google.com/g/2005#work_fax'
- WORK_MOBILE_REL = 'http://schemas.google.com/g/2005#work_mobile'
- WORK_PAGER_REL = 'http://schemas.google.com/g/2005#work_pager'
- NETMEETING_REL = 'http://schemas.google.com/g/2005#netmeeting'
- OVERALL_REL = 'http://schemas.google.com/g/2005#overall'
- PRICE_REL = 'http://schemas.google.com/g/2005#price'
- QUALITY_REL = 'http://schemas.google.com/g/2005#quality'
- EVENT_REL = 'http://schemas.google.com/g/2005#event'
- EVENT_ALTERNATE_REL = 'http://schemas.google.com/g/2005#event.alternate'
- EVENT_PARKING_REL = 'http://schemas.google.com/g/2005#event.parking'
- AIM_PROTOCOL = 'http://schemas.google.com/g/2005#AIM'
- MSN_PROTOCOL = 'http://schemas.google.com/g/2005#MSN'
- YAHOO_MESSENGER_PROTOCOL = 'http://schemas.google.com/g/2005#YAHOO'
- SKYPE_PROTOCOL = 'http://schemas.google.com/g/2005#SKYPE'
- QQ_PROTOCOL = 'http://schemas.google.com/g/2005#QQ'
- GOOGLE_TALK_PROTOCOL = 'http://schemas.google.com/g/2005#GOOGLE_TALK'
- ICQ_PROTOCOL = 'http://schemas.google.com/g/2005#ICQ'
- JABBER_PROTOCOL = 'http://schemas.google.com/g/2005#JABBER'
- REGULAR_COMMENTS = 'http://schemas.google.com/g/2005#regular'
- REVIEW_COMMENTS = 'http://schemas.google.com/g/2005#reviews'
- MAIL_BOTH = 'http://schemas.google.com/g/2005#both'
- MAIL_LETTERS = 'http://schemas.google.com/g/2005#letters'
- MAIL_PARCELS = 'http://schemas.google.com/g/2005#parcels'
- MAIL_NEITHER = 'http://schemas.google.com/g/2005#neither'
- GENERAL_ADDRESS = 'http://schemas.google.com/g/2005#general'
- LOCAL_ADDRESS = 'http://schemas.google.com/g/2005#local'
- OPTIONAL_ATENDEE = 'http://schemas.google.com/g/2005#event.optional'
- REQUIRED_ATENDEE = 'http://schemas.google.com/g/2005#event.required'
- ATTENDEE_ACCEPTED = 'http://schemas.google.com/g/2005#event.accepted'
- ATTENDEE_DECLINED = 'http://schemas.google.com/g/2005#event.declined'
- ATTENDEE_INVITED = 'http://schemas.google.com/g/2005#event.invited'
- ATTENDEE_TENTATIVE = 'http://schemas.google.com/g/2005#event.tentative'
- FULL_PROJECTION = 'full'
- VALUES_PROJECTION = 'values'
- BASIC_PROJECTION = 'basic'
- PRIVATE_VISIBILITY = 'private'
- PUBLIC_VISIBILITY = 'public'
- ACL_REL = 'http://schemas.google.com/acl/2007#accessControlList'
- class Error(Exception):
- pass
- class MissingRequiredParameters(Error):
- pass
- class LinkFinder(atom.data.LinkFinder):
- """Mixin used in Feed and Entry classes to simplify link lookups by type.
- Provides lookup methods for edit, edit-media, post, ACL and other special
- links which are common across Google Data APIs.
- """
- def find_html_link(self):
- """Finds the first link with rel of alternate and type of text/html."""
- for link in self.link:
- if link.rel == 'alternate' and link.type == 'text/html':
- return link.href
- return None
- FindHtmlLink = find_html_link
- def get_html_link(self):
- for a_link in self.link:
- if a_link.rel == 'alternate' and a_link.type == 'text/html':
- return a_link
- return None
- GetHtmlLink = get_html_link
- def find_post_link(self):
- """Get the URL to which new entries should be POSTed.
- The POST target URL is used to insert new entries.
- Returns:
- A str for the URL in the link with a rel matching the POST type.
- """
- return self.find_url('http://schemas.google.com/g/2005#post')
- FindPostLink = find_post_link
- def get_post_link(self):
- return self.get_link('http://schemas.google.com/g/2005#post')
- GetPostLink = get_post_link
- def find_acl_link(self):
- acl_link = self.get_acl_link()
- if acl_link:
- return acl_link.href
- return None
- FindAclLink = find_acl_link
- def get_acl_link(self):
- """Searches for a link or feed_link (if present) with the rel for ACL."""
- acl_link = self.get_link(ACL_REL)
- if acl_link:
- return acl_link
- elif hasattr(self, 'feed_link'):
- for a_feed_link in self.feed_link:
- if a_feed_link.rel == ACL_REL:
- return a_feed_link
- return None
- GetAclLink = get_acl_link
- def find_feed_link(self):
- return self.find_url('http://schemas.google.com/g/2005#feed')
- FindFeedLink = find_feed_link
- def get_feed_link(self):
- return self.get_link('http://schemas.google.com/g/2005#feed')
- GetFeedLink = get_feed_link
- def find_previous_link(self):
- return self.find_url('previous')
- FindPreviousLink = find_previous_link
- def get_previous_link(self):
- return self.get_link('previous')
- GetPreviousLink = get_previous_link
- class TotalResults(atom.core.XmlElement):
- """opensearch:TotalResults for a GData feed."""
- _qname = (OPENSEARCH_TEMPLATE_V1 % 'totalResults',
- OPENSEARCH_TEMPLATE_V2 % 'totalResults')
- class StartIndex(atom.core.XmlElement):
- """The opensearch:startIndex element in GData feed."""
- _qname = (OPENSEARCH_TEMPLATE_V1 % 'startIndex',
- OPENSEARCH_TEMPLATE_V2 % 'startIndex')
- class ItemsPerPage(atom.core.XmlElement):
- """The opensearch:itemsPerPage element in GData feed."""
- _qname = (OPENSEARCH_TEMPLATE_V1 % 'itemsPerPage',
- OPENSEARCH_TEMPLATE_V2 % 'itemsPerPage')
- class ExtendedProperty(atom.core.XmlElement):
- """The Google Data extendedProperty element.
- Used to store arbitrary key-value information specific to your
- application. The value can either be a text string stored as an XML
- attribute (.value), or an XML node (XmlBlob) as a child element.
- This element is used in the Google Calendar data API and the Google
- Contacts data API.
- """
- _qname = GDATA_TEMPLATE % 'extendedProperty'
- name = 'name'
- value = 'value'
- def get_xml_blob(self):
- """Returns the XML blob as an atom.core.XmlElement.
- Returns:
- An XmlElement representing the blob's XML, or None if no
- blob was set.
- """
- if self._other_elements:
- return self._other_elements[0]
- else:
- return None
- GetXmlBlob = get_xml_blob
- def set_xml_blob(self, blob):
- """Sets the contents of the extendedProperty to XML as a child node.
- Since the extendedProperty is only allowed one child element as an XML
- blob, setting the XML blob will erase any preexisting member elements
- in this object.
- Args:
- blob: str or atom.core.XmlElement representing the XML blob stored in
- the extendedProperty.
- """
- # Erase any existing extension_elements, clears the child nodes from the
- # extendedProperty.
- if isinstance(blob, atom.core.XmlElement):
- self._other_elements = [blob]
- else:
- self._other_elements = [atom.core.parse(str(blob))]
- SetXmlBlob = set_xml_blob
- class GDEntry(atom.data.Entry, LinkFinder):
- """Extends Atom Entry to provide data processing"""
- etag = '{http://schemas.google.com/g/2005}etag'
- def get_id(self):
- if self.id is not None and self.id.text is not None:
- return self.id.text.strip()
- return None
- GetId = get_id
- def is_media(self):
- if self.find_media_edit_link():
- return True
- return False
- IsMedia = is_media
- def find_media_link(self):
- """Returns the URL to the media content, if the entry is a media entry.
- Otherwise returns None.
- """
- if self.is_media():
- return self.content.src
- return None
- FindMediaLink = find_media_link
- class GDFeed(atom.data.Feed, LinkFinder):
- """A Feed from a GData service."""
- etag = '{http://schemas.google.com/g/2005}etag'
- total_results = TotalResults
- start_index = StartIndex
- items_per_page = ItemsPerPage
- entry = [GDEntry]
- def get_id(self):
- if self.id is not None and self.id.text is not None:
- return self.id.text.strip()
- return None
- GetId = get_id
- def get_generator(self):
- if self.generator and self.generator.text:
- return self.generator.text.strip()
- return None
- class BatchId(atom.core.XmlElement):
- """Identifies a single operation in a batch request."""
- _qname = BATCH_TEMPLATE % 'id'
- class BatchOperation(atom.core.XmlElement):
- """The CRUD operation which this batch entry represents."""
- _qname = BATCH_TEMPLATE % 'operation'
- type = 'type'
- class BatchStatus(atom.core.XmlElement):
- """The batch:status element present in a batch response entry.
- A status element contains the code (HTTP response code) and
- reason as elements. In a single request these fields would
- be part of the HTTP response, but in a batch request each
- Entry operation has a corresponding Entry in the response
- feed which includes status information.
- See http://code.google.com/apis/gdata/batch.html#Handling_Errors
- """
- _qname = BATCH_TEMPLATE % 'status'
- code = 'code'
- reason = 'reason'
- content_type = 'content-type'
- class BatchEntry(GDEntry):
- """An atom:entry for use in batch requests.
- The BatchEntry contains additional members to specify the operation to be
- performed on this entry and a batch ID so that the server can reference
- individual operations in the response feed. For more information, see:
- http://code.google.com/apis/gdata/batch.html
- """
- batch_operation = BatchOperation
- batch_id = BatchId
- batch_status = BatchStatus
- class BatchInterrupted(atom.core.XmlElement):
- """The batch:interrupted element sent if batch request was interrupted.
- Only appears in a feed if some of the batch entries could not be processed.
- See: http://code.google.com/apis/gdata/batch.html#Handling_Errors
- """
- _qname = BATCH_TEMPLATE % 'interrupted'
- reason = 'reason'
- success = 'success'
- failures = 'failures'
- parsed = 'parsed'
- class BatchFeed(GDFeed):
- """A feed containing a list of batch request entries."""
- interrupted = BatchInterrupted
- entry = [BatchEntry]
- def add_batch_entry(self, entry=None, id_url_string=None,
- batch_id_string=None, operation_string=None):
- """Logic for populating members of a BatchEntry and adding to the feed.
- If the entry is not a BatchEntry, it is converted to a BatchEntry so
- that the batch specific members will be present.
- The id_url_string can be used in place of an entry if the batch operation
- applies to a URL. For example query and delete operations require just
- the URL of an entry, no body is sent in the HTTP request. If an
- id_url_string is sent instead of an entry, a BatchEntry is created and
- added to the feed.
- This method also assigns the desired batch id to the entry so that it
- can be referenced in the server's response. If the batch_id_string is
- None, this method will assign a batch_id to be the index at which this
- entry will be in the feed's entry list.
- Args:
- entry: BatchEntry, atom.data.Entry, or another Entry flavor (optional)
- The entry which will be sent to the server as part of the batch
- request. The item must have a valid atom id so that the server
- knows which entry this request references.
- id_url_string: str (optional) The URL of the entry to be acted on. You
- can find this URL in the text member of the atom id for an entry.
- If an entry is not sent, this id will be used to construct a new
- BatchEntry which will be added to the request feed.
- batch_id_string: str (optional) The batch ID to be used to reference
- this batch operation in the results feed. If this parameter is None,
- the current length of the feed's entry array will be used as a
- count. Note that batch_ids should either always be specified or
- never, mixing could potentially result in duplicate batch ids.
- operation_string: str (optional) The desired batch operation which will
- set the batch_operation.type member of the entry. Options are
- 'insert', 'update', 'delete', and 'query'
- Raises:
- MissingRequiredParameters: Raised if neither an id_ url_string nor an
- entry are provided in the request.
- Returns:
- The added entry.
- """
- if entry is None and id_url_string is None:
- raise MissingRequiredParameters('supply either an entry or URL string')
- if entry is None and id_url_string is not None:
- entry = BatchEntry(id=atom.data.Id(text=id_url_string))
- if batch_id_string is not None:
- entry.batch_id = BatchId(text=batch_id_string)
- elif entry.batch_id is None or entry.batch_id.text is None:
- entry.batch_id = BatchId(text=str(len(self.entry)))
- if operation_string is not None:
- entry.batch_operation = BatchOperation(type=operation_string)
- self.entry.append(entry)
- return entry
- AddBatchEntry = add_batch_entry
- def add_insert(self, entry, batch_id_string=None):
- """Add an insert request to the operations in this batch request feed.
- If the entry doesn't yet have an operation or a batch id, these will
- be set to the insert operation and a batch_id specified as a parameter.
- Args:
- entry: BatchEntry The entry which will be sent in the batch feed as an
- insert request.
- batch_id_string: str (optional) The batch ID to be used to reference
- this batch operation in the results feed. If this parameter is None,
- the current length of the feed's entry array will be used as a
- count. Note that batch_ids should either always be specified or
- never, mixing could potentially result in duplicate batch ids.
- """
- self.add_batch_entry(entry=entry, batch_id_string=batch_id_string,
- operation_string=BATCH_INSERT)
- AddInsert = add_insert
- def add_update(self, entry, batch_id_string=None):
- """Add an update request to the list of batch operations in this feed.
- Sets the operation type of the entry to insert if it is not already set
- and assigns the desired batch id to the entry so that it can be
- referenced in the server's response.
- Args:
- entry: BatchEntry The entry which will be sent to the server as an
- update (HTTP PUT) request. The item must have a valid atom id
- so that the server knows which entry to replace.
- batch_id_string: str (optional) The batch ID to be used to reference
- this batch operation in the results feed. If this parameter is None,
- the current length of the feed's entry array will be used as a
- count. See also comments for AddInsert.
- """
- self.add_batch_entry(entry=entry, batch_id_string=batch_id_string,
- operation_string=BATCH_UPDATE)
- AddUpdate = add_update
- def add_delete(self, url_string=None, entry=None, batch_id_string=None):
- """Adds a delete request to the batch request feed.
- This method takes either the url_string which is the atom id of the item
- to be deleted, or the entry itself. The atom id of the entry must be
- present so that the server knows which entry should be deleted.
- Args:
- url_string: str (optional) The URL of the entry to be deleted. You can
- find this URL in the text member of the atom id for an entry.
- entry: BatchEntry (optional) The entry to be deleted.
- batch_id_string: str (optional)
- Raises:
- MissingRequiredParameters: Raised if neither a url_string nor an entry
- are provided in the request.
- """
- self.add_batch_entry(entry=entry, id_url_string=url_string,
- batch_id_string=batch_id_string, operation_string=BATCH_DELETE)
- AddDelete = add_delete
- def add_query(self, url_string=None, entry=None, batch_id_string=None):
- """Adds a query request to the batch request feed.
- This method takes either the url_string which is the query URL
- whose results will be added to the result feed. The query URL will
- be encapsulated in a BatchEntry, and you may pass in the BatchEntry
- with a query URL instead of sending a url_string.
- Args:
- url_string: str (optional)
- entry: BatchEntry (optional)
- batch_id_string: str (optional)
- Raises:
- MissingRequiredParameters
- """
- self.add_batch_entry(entry=entry, id_url_string=url_string,
- batch_id_string=batch_id_string, operation_string=BATCH_QUERY)
- AddQuery = add_query
- def find_batch_link(self):
- return self.find_url('http://schemas.google.com/g/2005#batch')
- FindBatchLink = find_batch_link
- class EntryLink(atom.core.XmlElement):
- """The gd:entryLink element.
- Represents a logically nested entry. For example, a <gd:who>
- representing a contact might have a nested entry from a contact feed.
- """
- _qname = GDATA_TEMPLATE % 'entryLink'
- entry = GDEntry
- rel = 'rel'
- read_only = 'readOnly'
- href = 'href'
- class FeedLink(atom.core.XmlElement):
- """The gd:feedLink element.
- Represents a logically nested feed. For example, a calendar feed might
- have a nested feed representing all comments on entries.
- """
- _qname = GDATA_TEMPLATE % 'feedLink'
- feed = GDFeed
- rel = 'rel'
- read_only = 'readOnly'
- count_hint = 'countHint'
- href = 'href'
- class AdditionalName(atom.core.XmlElement):
- """The gd:additionalName element.
- Specifies additional (eg. middle) name of the person.
- Contains an attribute for the phonetic representaton of the name.
- """
- _qname = GDATA_TEMPLATE % 'additionalName'
- yomi = 'yomi'
- class Comments(atom.core.XmlElement):
- """The gd:comments element.
- Contains a comments feed for the enclosing entry (such as a calendar event).
- """
- _qname = GDATA_TEMPLATE % 'comments'
- rel = 'rel'
- feed_link = FeedLink
- class Country(atom.core.XmlElement):
- """The gd:country element.
- Country name along with optional country code. The country code is
- given in accordance with ISO 3166-1 alpha-2:
- http://www.iso.org/iso/iso-3166-1_decoding_table
- """
- _qname = GDATA_TEMPLATE % 'country'
- code = 'code'
- class EmailImParent(atom.core.XmlElement):
- address = 'address'
- label = 'label'
- rel = 'rel'
- primary = 'primary'
- class Email(EmailImParent):
- """The gd:email element.
- An email address associated with the containing entity (which is
- usually an entity representing a person or a location).
- """
- _qname = GDATA_TEMPLATE % 'email'
- display_name = 'displayName'
- class FamilyName(atom.core.XmlElement):
- """The gd:familyName element.
- Specifies family name of the person, eg. "Smith".
- """
- _qname = GDATA_TEMPLATE % 'familyName'
- yomi = 'yomi'
- class Im(EmailImParent):
- """The gd:im element.
- An instant messaging address associated with the containing entity.
- """
- _qname = GDATA_TEMPLATE % 'im'
- protocol = 'protocol'
- class GivenName(atom.core.XmlElement):
- """The gd:givenName element.
- Specifies given name of the person, eg. "John".
- """
- _qname = GDATA_TEMPLATE % 'givenName'
- yomi = 'yomi'
- class NamePrefix(atom.core.XmlElement):
- """The gd:namePrefix element.
- Honorific prefix, eg. 'Mr' or 'Mrs'.
- """
- _qname = GDATA_TEMPLATE % 'namePrefix'
- class NameSuffix(atom.core.XmlElement):
- """The gd:nameSuffix element.
- Honorific suffix, eg. 'san' or 'III'.
- """
- _qname = GDATA_TEMPLATE % 'nameSuffix'
- class FullName(atom.core.XmlElement):
- """The gd:fullName element.
- Unstructured representation of the name.
- """
- _qname = GDATA_TEMPLATE % 'fullName'
- class Name(atom.core.XmlElement):
- """The gd:name element.
- Allows storing person's name in a structured way. Consists of
- given name, additional name, family name, prefix, suffix and full name.
- """
- _qname = GDATA_TEMPLATE % 'name'
- given_name = GivenName
- additional_name = AdditionalName
- family_name = FamilyName
- name_prefix = NamePrefix
- name_suffix = NameSuffix
- full_name = FullName
- class OrgDepartment(atom.core.XmlElement):
- """The gd:orgDepartment element.
- Describes a department within an organization. Must appear within a
- gd:organization element.
- """
- _qname = GDATA_TEMPLATE % 'orgDepartment'
- class OrgJobDescription(atom.core.XmlElement):
- """The gd:orgJobDescription element.
- Describes a job within an organization. Must appear within a
- gd:organization element.
- """
- _qname = GDATA_TEMPLATE % 'orgJobDescription'
- class OrgName(atom.core.XmlElement):
- """The gd:orgName element.
- The name of the organization. Must appear within a gd:organization
- element.
- Contains a Yomigana attribute (Japanese reading aid) for the
- organization name.
- """
- _qname = GDATA_TEMPLATE % 'orgName'
- yomi = 'yomi'
- class OrgSymbol(atom.core.XmlElement):
- """The gd:orgSymbol element.
- Provides a symbol of an organization. Must appear within a
- gd:organization element.
- """
- _qname = GDATA_TEMPLATE % 'orgSymbol'
- class OrgTitle(atom.core.XmlElement):
- """The gd:orgTitle element.
- The title of a person within an organization. Must appear within a
- gd:organization element.
- """
- _qname = GDATA_TEMPLATE % 'orgTitle'
- class Organization(atom.core.XmlElement):
- """The gd:organization element.
- An organization, typically associated with a contact.
- """
- _qname = GDATA_TEMPLATE % 'organization'
- label = 'label'
- primary = 'primary'
- rel = 'rel'
- department = OrgDepartment
- job_description = OrgJobDescription
- name = OrgName
- symbol = OrgSymbol
- title = OrgTitle
- class When(atom.core.XmlElement):
- """The gd:when element.
- Represents a period of time or an instant.
- """
- _qname = GDATA_TEMPLATE % 'when'
- end = 'endTime'
- start = 'startTime'
- value = 'valueString'
- class OriginalEvent(atom.core.XmlElement):
- """The gd:originalEvent element.
- Equivalent to the Recurrence ID property specified in section 4.8.4.4
- of RFC 2445. Appears in every instance of a recurring event, to identify
- the original event.
- Contains a <gd:when> element specifying the original start time of the
- instance that has become an exception.
- """
- _qname = GDATA_TEMPLATE % 'originalEvent'
- id = 'id'
- href = 'href'
- when = When
- class PhoneNumber(atom.core.XmlElement):
- """The gd:phoneNumber element.
- A phone number associated with the containing entity (which is usually
- an entity representing a person or a location).
- """
- _qname = GDATA_TEMPLATE % 'phoneNumber'
- label = 'label'
- rel = 'rel'
- uri = 'uri'
- primary = 'primary'
- class PostalAddress(atom.core.XmlElement):
- """The gd:postalAddress element."""
- _qname = GDATA_TEMPLATE % 'postalAddress'
- label = 'label'
- rel = 'rel'
- uri = 'uri'
- primary = 'primary'
- class Rating(atom.core.XmlElement):
- """The gd:rating element.
- Represents a numeric rating of the enclosing entity, such as a
- comment. Each rating supplies its own scale, although it may be
- normalized by a service; for example, some services might convert all
- ratings to a scale from 1 to 5.
- """
- _qname = GDATA_TEMPLATE % 'rating'
- average = 'average'
- max = 'max'
- min = 'min'
- num_raters = 'numRaters'
- rel = 'rel'
- value = 'value'
- class Recurrence(atom.core.XmlElement):
- """The gd:recurrence element.
- Represents the dates and times when a recurring event takes place.
- The string that defines the recurrence consists of a set of properties,
- each of which is defined in the iCalendar standard (RFC 2445).
- Specifically, the string usually begins with a DTSTART property that
- indicates the starting time of the first instance of the event, and
- often a DTEND property or a DURATION property to indicate when the
- first instance ends. Next come RRULE, RDATE, EXRULE, and/or EXDATE
- properties, which collectively define a recurring event and its
- exceptions (but see below). (See section 4.8.5 of RFC 2445 for more
- information about these recurrence component properties.) Last comes a
- VTIMEZONE component, providing detailed timezone rules for any timezone
- ID mentioned in the preceding properties.
- Google services like Google Calendar don't generally generate EXRULE
- and EXDATE properties to represent exceptions to recurring events;
- instead, they generate <gd:recurrenceException> elements. However,
- Google services may include EXRULE and/or EXDATE properties anyway;
- for example, users can import events and exceptions into Calendar, and
- if those imported events contain EXRULE or EXDATE properties, then
- Calendar will provide those properties when it sends a <gd:recurrence>
- element.
- Note the the use of <gd:recurrenceException> means that you can't be
- sure just from examining a <gd:recurrence> element whether there are
- any exceptions to the recurrence description. To ensure that you find
- all exceptions, look for <gd:recurrenceException> elements in the feed,
- and use their <gd:originalEvent> elements to match them up with
- <gd:recurrence> elements.
- """
- _qname = GDATA_TEMPLATE % 'recurrence'
- class RecurrenceException(atom.core.XmlElement):
- """The gd:recurrenceException element.
- Represents an event that's an exception to a recurring event-that is,
- an instance of a recurring event in which one or more aspects of the
- recurring event (such as attendance list, time, or location) have been
- changed.
- Contains a <gd:originalEvent> element that specifies the original
- recurring event that this event is an exception to.
- When you change an instance of a recurring event, that instance becomes
- an exception. Depending on what change you made to it, the exception
- behaves in either of two different ways when the original recurring
- event is changed:
- - If you add, change, or remove comments, attendees, or attendee
- responses, then the exception remains tied to the original event, and
- changes to the original event also change the exception.
- - If you make any other changes to the exception (such as changing the
- time or location) then the instance becomes "specialized," which means
- that it's no longer as tightly tied to the original event. If you
- change the original event, specialized exceptions don't change. But
- see below.
- For example, say you have a meeting every Tuesday and Thursday at
- 2:00 p.m. If you change the attendance list for this Thursday's meeting
- (but not for the regularly scheduled meeting), then it becomes an
- exception. If you change the time for this Thursday's meeting (but not
- for the regularly scheduled meeting), then it becomes specialized.
- Regardless of whether an exception is specialized or not, if you do
- something that deletes the instance that the exception was derived from,
- then the exception is deleted. Note that changing the day or time of a
- recurring event deletes all instances, and creates new ones.
- For example, after you've specialized this Thursday's meeting, say you
- change the recurring meeting to happen on Monday, Wednesday, and Friday.
- That change deletes all of the recurring instances of the
- Tuesday/Thursday meeting, including the specialized one.
- If a particular instance of a recurring event is deleted, then that
- instance appears as a <gd:recurrenceException> containing a
- <gd:entryLink> that has its <gd:eventStatus> set to
- "http://schemas.google.com/g/2005#event.canceled". (For more
- information about canceled events, see RFC 2445.)
- """
- _qname = GDATA_TEMPLATE % 'recurrenceException'
- specialized = 'specialized'
- entry_link = EntryLink
- original_event = OriginalEvent
- class Reminder(atom.core.XmlElement):
- """The gd:reminder element.
- A time interval, indicating how long before the containing entity's start
- time or due time attribute a reminder should be issued. Alternatively,
- may specify an absolute time at which a reminder should be issued. Also
- specifies a notification method, indicating what medium the system
- should use to remind the user.
- """
- _qname = GDATA_TEMPLATE % 'reminder'
- absolute_time = 'absoluteTime'
- method = 'method'
- days = 'days'
- hours = 'hours'
- minutes = 'minutes'
- class Agent(atom.core.XmlElement):
- """The gd:agent element.
- The agent who actually receives the mail. Used in work addresses.
- Also for 'in care of' or 'c/o'.
- """
- _qname = GDATA_TEMPLATE % 'agent'
- class HouseName(atom.core.XmlElement):
- """The gd:housename element.
- Used in places where houses or buildings have names (and not
- necessarily numbers), eg. "The Pillars".
- """
- _qname = GDATA_TEMPLATE % 'housename'
- class Street(atom.core.XmlElement):
- """The gd:street element.
- Can be street, avenue, road, etc. This element also includes the
- house number and room/apartment/flat/floor number.
- """
- _qname = GDATA_TEMPLATE % 'street'
- class PoBox(atom.core.XmlElement):
- """The gd:pobox element.
- Covers actual P.O. boxes, drawers, locked bags, etc. This is usually
- but not always mutually exclusive with street.
- """
- _qname = GDATA_TEMPLATE % 'pobox'
- class Neighborhood(atom.core.XmlElement):
- """The gd:neighborhood element.
- This is used to disambiguate a street address when a city contains more
- than one street with the same name, or to specify a small place whose
- mail is routed through a larger postal town. In China it could be a
- county or a minor city.
- """
- _qname = GDATA_TEMPLATE % 'neighborhood'
- class City(atom.core.XmlElement):
- """The gd:city element.
- Can be city, village, town, borough, etc. This is the postal town and
- not necessarily the place of residence or place of business.
- """
- _qname = GDATA_TEMPLATE % 'city'
- class Subregion(atom.core.XmlElement):
- """The gd:subregion element.
- Handles administrative districts such as U.S. or U.K. counties that are
- not used for mail addressing purposes. Subregion is not intended for
- delivery addresses.
- """
- _qname = GDATA_TEMPLATE % 'subregion'
- class Region(atom.core.XmlElement):
- """The gd:region element.
- A state, province, county (in Ireland), Land (in Germany),
- departement (in France), etc.
- """
- _qname = GDATA_TEMPLATE % 'region'
- class Postcode(atom.core.XmlElement):
- """The gd:postcode element.
- Postal code. Usually country-wide, but sometimes specific to the
- city (e.g. "2" in "Dublin 2, Ireland" addresses).
- """
- _qname = GDATA_TEMPLATE % 'postcode'
- class Country(atom.core.XmlElement):
- """The gd:country element.
- The name or code of the country.
- """
- _qname = GDATA_TEMPLATE % 'country'
- class FormattedAddress(atom.core.XmlElement):
- """The gd:formattedAddress element.
- The full, unstructured postal address.
- """
- _qname = GDATA_TEMPLATE % 'formattedAddress'
- class StructuredPostalAddress(atom.core.XmlElement):
- """The gd:structuredPostalAddress element.
- Postal address split into components. It allows to store the address
- in locale independent format. The fields can be interpreted and used
- to generate formatted, locale dependent address. The following elements
- reperesent parts of the address: agent, house name, street, P.O. box,
- neighborhood, city, subregion, region, postal code, country. The
- subregion element is not used for postal addresses, it is provided for
- extended uses of addresses only. In order to store postal address in an
- unstructured form formatted address field is provided.
- """
- _qname = GDATA_TEMPLATE % 'structuredPostalAddress'
- rel = 'rel'
- mail_class = 'mailClass'
- usage = 'usage'
- label = 'label'
- primary = 'primary'
- agent = Agent
- house_name = HouseName
- street = Street
- po_box = PoBox
- neighborhood = Neighborhood
- city = City
- subregion = Subregion
- region = Region
- postcode = Postcode
- country = Country
- formatted_address = FormattedAddress
- class Where(atom.core.XmlElement):
- """The gd:where element.
- A place (such as an event location) associated with the containing
- entity. The type of the association is determined by the rel attribute;
- the details of the location are contained in an embedded or linked-to
- Contact entry.
- A <gd:where> element is more general than a <gd:geoPt> element. The
- former identifies a place using a text description and/or a Contact
- entry, while the latter identifies a place using a specific geographic
- location.
- """
- _qname = GDATA_TEMPLATE % 'where'
- label = 'label'
- rel = 'rel'
- value = 'valueString'
- entry_link = EntryLink
- class AttendeeType(atom.core.XmlElement):
- """The gd:attendeeType element."""
- _qname = GDATA_TEMPLATE % 'attendeeType'
- value = 'value'
- class AttendeeStatus(atom.core.XmlElement):
- """The gd:attendeeStatus element."""
- _qname = GDATA_TEMPLATE % 'attendeeStatus'
- value = 'value'
- class Who(atom.core.XmlElement):
- """The gd:who element.
- A person associated with the containing entity. The type of the
- association is determined by the rel attribute; the details about the
- person are contained in an embedded or linked-to Contact entry.
- The <gd:who> element can be used to specify email senders and
- recipients, calendar event organizers, and so on.
- """
- _qname = GDATA_TEMPLATE % 'who'
- email = 'email'
- rel = 'rel'
- value = 'valueString'
- attendee_status = AttendeeStatus
- attendee_type = AttendeeType
- entry_link = EntryLink
- class Deleted(atom.core.XmlElement):
- """gd:deleted when present, indicates the containing entry is deleted."""
- _qname = GD_TEMPLATE % 'deleted'
- class Money(atom.core.XmlElement):
- """Describes money"""
- _qname = GD_TEMPLATE % 'money'
- amount = 'amount'
- currency_code = 'currencyCode'
- class MediaSource(object):
- """GData Entries can refer to media sources, so this class provides a
- place to store references to these objects along with some metadata.
- """
- def __init__(self, file_handle=None, content_type=None, content_length=None,
- file_path=None, file_name=None):
- """Creates an object of type MediaSource.
- Args:
- file_handle: A file handle pointing to the file to be encapsulated in the
- MediaSource.
- content_type: string The MIME type of the file. Required if a file_handle
- is given.
- content_length: int The size of the file. Required if a file_handle is
- given.
- file_path: string (optional) A full path name to the file. Used in
- place of a file_handle.
- file_name: string The name of the file without any path information.
- Required if a file_handle is given.
- """
- self.file_handle = file_handle
- self.content_type = content_type
- self.content_length = content_length
- self.file_name = file_name
- if (file_handle is None and content_type is not None and
- file_path is not None):
- self.set_file_handle(file_path, content_type)
- def set_file_handle(self, file_name, content_type):
- """A helper function which can create a file handle from a given filename
- and set the content type and length all at once.
- Args:
- file_name: string The path and file name to the file containing the media
- content_type: string A MIME type representing the type of the media
- """
- self.file_handle = open(file_name, 'rb')
- self.content_type = content_type
- self.content_length = os.path.getsize(file_name)
- self.file_name = os.path.basename(file_name)
- SetFileHandle = set_file_handle
- def modify_request(self, http_request):
- http_request.add_body_part(self.file_handle, self.content_type,
- self.content_length)
- return http_request
- ModifyRequest = modify_request