#!/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. __author__ = 'j.s@google.com (Jeff Scudder)' import atom.core XML_TEMPLATE = '{http://www.w3.org/XML/1998/namespace}%s' ATOM_TEMPLATE = '{http://www.w3.org/2005/Atom}%s' APP_TEMPLATE_V1 = '{http://purl.org/atom/app#}%s' APP_TEMPLATE_V2 = '{http://www.w3.org/2007/app}%s' class Name(atom.core.XmlElement): """The atom:name element.""" _qname = ATOM_TEMPLATE % 'name' class Email(atom.core.XmlElement): """The atom:email element.""" _qname = ATOM_TEMPLATE % 'email' class Uri(atom.core.XmlElement): """The atom:uri element.""" _qname = ATOM_TEMPLATE % 'uri' class Person(atom.core.XmlElement): """A foundation class which atom:author and atom:contributor extend. A person contains information like name, email address, and web page URI for an author or contributor to an Atom feed. """ name = Name email = Email uri = Uri class Author(Person): """The atom:author element. An author is a required element in Feed unless each Entry contains an Author. """ _qname = ATOM_TEMPLATE % 'author' class Contributor(Person): """The atom:contributor element.""" _qname = ATOM_TEMPLATE % 'contributor' class Link(atom.core.XmlElement): """The atom:link element.""" _qname = ATOM_TEMPLATE % 'link' href = 'href' rel = 'rel' type = 'type' hreflang = 'hreflang' title = 'title' length = 'length' class Generator(atom.core.XmlElement): """The atom:generator element.""" _qname = ATOM_TEMPLATE % 'generator' uri = 'uri' version = 'version' class Text(atom.core.XmlElement): """A foundation class from which atom:title, summary, etc. extend. This class should never be instantiated. """ type = 'type' class Title(Text): """The atom:title element.""" _qname = ATOM_TEMPLATE % 'title' class Subtitle(Text): """The atom:subtitle element.""" _qname = ATOM_TEMPLATE % 'subtitle' class Rights(Text): """The atom:rights element.""" _qname = ATOM_TEMPLATE % 'rights' class Summary(Text): """The atom:summary element.""" _qname = ATOM_TEMPLATE % 'summary' class Content(Text): """The atom:content element.""" _qname = ATOM_TEMPLATE % 'content' src = 'src' class Category(atom.core.XmlElement): """The atom:category element.""" _qname = ATOM_TEMPLATE % 'category' term = 'term' scheme = 'scheme' label = 'label' class Id(atom.core.XmlElement): """The atom:id element.""" _qname = ATOM_TEMPLATE % 'id' class Icon(atom.core.XmlElement): """The atom:icon element.""" _qname = ATOM_TEMPLATE % 'icon' class Logo(atom.core.XmlElement): """The atom:logo element.""" _qname = ATOM_TEMPLATE % 'logo' class Draft(atom.core.XmlElement): """The app:draft element which indicates if this entry should be public.""" _qname = (APP_TEMPLATE_V1 % 'draft', APP_TEMPLATE_V2 % 'draft') class Control(atom.core.XmlElement): """The app:control element indicating restrictions on publication. The APP control element may contain a draft element indicating whether or not this entry should be publicly available. """ _qname = (APP_TEMPLATE_V1 % 'control', APP_TEMPLATE_V2 % 'control') draft = Draft class Date(atom.core.XmlElement): """A parent class for atom:updated, published, etc.""" class Updated(Date): """The atom:updated element.""" _qname = ATOM_TEMPLATE % 'updated' class Published(Date): """The atom:published element.""" _qname = ATOM_TEMPLATE % 'published' class LinkFinder(object): """An "interface" providing methods to find link elements Entry elements often contain multiple links which differ in the rel attribute or content type. Often, developers are interested in a specific type of link so this class provides methods to find specific classes of links. This class is used as a mixin in Atom entries and feeds. """ def find_url(self, rel): """Returns the URL in a link with the desired rel value.""" for link in self.link: if link.rel == rel and link.href: return link.href return None FindUrl = find_url def get_link(self, rel): """Returns a link object which has the desired rel value. If you are interested in the URL instead of the link object, consider using find_url instead. """ for link in self.link: if link.rel == rel and link.href: return link return None GetLink = get_link def find_self_link(self): """Find the first link with rel set to 'self' Returns: A str containing the link's href or None if none of the links had rel equal to 'self' """ return self.find_url('self') FindSelfLink = find_self_link def get_self_link(self): return self.get_link('self') GetSelfLink = get_self_link def find_edit_link(self): return self.find_url('edit') FindEditLink = find_edit_link def get_edit_link(self): return self.get_link('edit') GetEditLink = get_edit_link def find_edit_media_link(self): link = self.find_url('edit-media') # Search for media-edit as well since Picasa API used media-edit instead. if link is None: return self.find_url('media-edit') return link FindEditMediaLink = find_edit_media_link def get_edit_media_link(self): link = self.get_link('edit-media') if link is None: return self.get_link('media-edit') return link GetEditMediaLink = get_edit_media_link def find_next_link(self): return self.find_url('next') FindNextLink = find_next_link def get_next_link(self): return self.get_link('next') GetNextLink = get_next_link def find_license_link(self): return self.find_url('license') FindLicenseLink = find_license_link def get_license_link(self): return self.get_link('license') GetLicenseLink = get_license_link def find_alternate_link(self): return self.find_url('alternate') FindAlternateLink = find_alternate_link def get_alternate_link(self): return self.get_link('alternate') GetAlternateLink = get_alternate_link class FeedEntryParent(atom.core.XmlElement, LinkFinder): """A super class for atom:feed and entry, contains shared attributes""" author = [Author] category = [Category] contributor = [Contributor] id = Id link = [Link] rights = Rights title = Title updated = Updated def __init__(self, atom_id=None, text=None, *args, **kwargs): if atom_id is not None: self.id = atom_id atom.core.XmlElement.__init__(self, text=text, *args, **kwargs) class Source(FeedEntryParent): """The atom:source element.""" _qname = ATOM_TEMPLATE % 'source' generator = Generator icon = Icon logo = Logo subtitle = Subtitle class Entry(FeedEntryParent): """The atom:entry element.""" _qname = ATOM_TEMPLATE % 'entry' content = Content published = Published source = Source summary = Summary control = Control class Feed(Source): """The atom:feed element which contains entries.""" _qname = ATOM_TEMPLATE % 'feed' entry = [Entry] class ExtensionElement(atom.core.XmlElement): """Provided for backwards compatibility to the v1 atom.ExtensionElement.""" def __init__(self, tag=None, namespace=None, attributes=None, children=None, text=None, *args, **kwargs): if namespace: self._qname = '{%s}%s' % (namespace, tag) else: self._qname = tag self.children = children or [] self.attributes = attributes or {} self.text = text _BecomeChildElement = atom.core.XmlElement._become_child