| #!/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 |
| |
| |