1485 lines
48 KiB
Python
1485 lines
48 KiB
Python
|
#!/usr/bin/python
|
||
|
#
|
||
|
# Copyright (C) 2006 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.
|
||
|
|
||
|
|
||
|
"""Contains classes representing Atom elements.
|
||
|
|
||
|
Module objective: provide data classes for Atom constructs. These classes hide
|
||
|
the XML-ness of Atom and provide a set of native Python classes to interact
|
||
|
with.
|
||
|
|
||
|
Conversions to and from XML should only be necessary when the Atom classes
|
||
|
"touch the wire" and are sent over HTTP. For this reason this module
|
||
|
provides methods and functions to convert Atom classes to and from strings.
|
||
|
|
||
|
For more information on the Atom data model, see RFC 4287
|
||
|
(http://www.ietf.org/rfc/rfc4287.txt)
|
||
|
|
||
|
AtomBase: A foundation class on which Atom classes are built. It
|
||
|
handles the parsing of attributes and children which are common to all
|
||
|
Atom classes. By default, the AtomBase class translates all XML child
|
||
|
nodes into ExtensionElements.
|
||
|
|
||
|
ExtensionElement: Atom allows Atom objects to contain XML which is not part
|
||
|
of the Atom specification, these are called extension elements. If a
|
||
|
classes parser encounters an unexpected XML construct, it is translated
|
||
|
into an ExtensionElement instance. ExtensionElement is designed to fully
|
||
|
capture the information in the XML. Child nodes in an XML extension are
|
||
|
turned into ExtensionElements as well.
|
||
|
"""
|
||
|
|
||
|
|
||
|
__author__ = 'api.jscudder (Jeffrey Scudder)'
|
||
|
|
||
|
try:
|
||
|
from xml.etree import cElementTree as ElementTree
|
||
|
except ImportError:
|
||
|
try:
|
||
|
import cElementTree as ElementTree
|
||
|
except ImportError:
|
||
|
try:
|
||
|
from xml.etree import ElementTree
|
||
|
except ImportError:
|
||
|
from elementtree import ElementTree
|
||
|
import warnings
|
||
|
|
||
|
|
||
|
# XML namespaces which are often used in Atom entities.
|
||
|
ATOM_NAMESPACE = 'http://www.w3.org/2005/Atom'
|
||
|
ELEMENT_TEMPLATE = '{http://www.w3.org/2005/Atom}%s'
|
||
|
APP_NAMESPACE = 'http://purl.org/atom/app#'
|
||
|
APP_TEMPLATE = '{http://purl.org/atom/app#}%s'
|
||
|
|
||
|
# This encoding is used for converting strings before translating the XML
|
||
|
# into an object.
|
||
|
XML_STRING_ENCODING = 'utf-8'
|
||
|
# The desired string encoding for object members. set or monkey-patch to
|
||
|
# unicode if you want object members to be Python unicode strings, instead of
|
||
|
# encoded strings
|
||
|
MEMBER_STRING_ENCODING = 'utf-8'
|
||
|
#MEMBER_STRING_ENCODING = unicode
|
||
|
|
||
|
# If True, all methods which are exclusive to v1 will raise a
|
||
|
# DeprecationWarning
|
||
|
ENABLE_V1_WARNINGS = False
|
||
|
|
||
|
|
||
|
def v1_deprecated(warning=None):
|
||
|
"""Shows a warning if ENABLE_V1_WARNINGS is True.
|
||
|
|
||
|
Function decorator used to mark methods used in v1 classes which
|
||
|
may be removed in future versions of the library.
|
||
|
"""
|
||
|
warning = warning or ''
|
||
|
# This closure is what is returned from the deprecated function.
|
||
|
def mark_deprecated(f):
|
||
|
# The deprecated_function wraps the actual call to f.
|
||
|
def optional_warn_function(*args, **kwargs):
|
||
|
if ENABLE_V1_WARNINGS:
|
||
|
warnings.warn(warning, DeprecationWarning, stacklevel=2)
|
||
|
return f(*args, **kwargs)
|
||
|
# Preserve the original name to avoid masking all decorated functions as
|
||
|
# 'deprecated_function'
|
||
|
try:
|
||
|
optional_warn_function.func_name = f.func_name
|
||
|
except TypeError:
|
||
|
pass # In Python2.3 we can't set the func_name
|
||
|
return optional_warn_function
|
||
|
return mark_deprecated
|
||
|
|
||
|
|
||
|
def CreateClassFromXMLString(target_class, xml_string, string_encoding=None):
|
||
|
"""Creates an instance of the target class from the string contents.
|
||
|
|
||
|
Args:
|
||
|
target_class: class The class which will be instantiated and populated
|
||
|
with the contents of the XML. This class must have a _tag and a
|
||
|
_namespace class variable.
|
||
|
xml_string: str A string which contains valid XML. The root element
|
||
|
of the XML string should match the tag and namespace of the desired
|
||
|
class.
|
||
|
string_encoding: str The character encoding which the xml_string should
|
||
|
be converted to before it is interpreted and translated into
|
||
|
objects. The default is None in which case the string encoding
|
||
|
is not changed.
|
||
|
|
||
|
Returns:
|
||
|
An instance of the target class with members assigned according to the
|
||
|
contents of the XML - or None if the root XML tag and namespace did not
|
||
|
match those of the target class.
|
||
|
"""
|
||
|
encoding = string_encoding or XML_STRING_ENCODING
|
||
|
if encoding and isinstance(xml_string, unicode):
|
||
|
xml_string = xml_string.encode(encoding)
|
||
|
tree = ElementTree.fromstring(xml_string)
|
||
|
return _CreateClassFromElementTree(target_class, tree)
|
||
|
|
||
|
|
||
|
CreateClassFromXMLString = v1_deprecated(
|
||
|
'Please use atom.core.parse with atom.data classes instead.')(
|
||
|
CreateClassFromXMLString)
|
||
|
|
||
|
|
||
|
def _CreateClassFromElementTree(target_class, tree, namespace=None, tag=None):
|
||
|
"""Instantiates the class and populates members according to the tree.
|
||
|
|
||
|
Note: Only use this function with classes that have _namespace and _tag
|
||
|
class members.
|
||
|
|
||
|
Args:
|
||
|
target_class: class The class which will be instantiated and populated
|
||
|
with the contents of the XML.
|
||
|
tree: ElementTree An element tree whose contents will be converted into
|
||
|
members of the new target_class instance.
|
||
|
namespace: str (optional) The namespace which the XML tree's root node must
|
||
|
match. If omitted, the namespace defaults to the _namespace of the
|
||
|
target class.
|
||
|
tag: str (optional) The tag which the XML tree's root node must match. If
|
||
|
omitted, the tag defaults to the _tag class member of the target
|
||
|
class.
|
||
|
|
||
|
Returns:
|
||
|
An instance of the target class - or None if the tag and namespace of
|
||
|
the XML tree's root node did not match the desired namespace and tag.
|
||
|
"""
|
||
|
if namespace is None:
|
||
|
namespace = target_class._namespace
|
||
|
if tag is None:
|
||
|
tag = target_class._tag
|
||
|
if tree.tag == '{%s}%s' % (namespace, tag):
|
||
|
target = target_class()
|
||
|
target._HarvestElementTree(tree)
|
||
|
return target
|
||
|
else:
|
||
|
return None
|
||
|
|
||
|
|
||
|
class ExtensionContainer(object):
|
||
|
|
||
|
def __init__(self, extension_elements=None, extension_attributes=None,
|
||
|
text=None):
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
self.text = text
|
||
|
|
||
|
__init__ = v1_deprecated(
|
||
|
'Please use data model classes in atom.data instead.')(
|
||
|
__init__)
|
||
|
|
||
|
# Three methods to create an object from an ElementTree
|
||
|
def _HarvestElementTree(self, tree):
|
||
|
# Fill in the instance members from the contents of the XML tree.
|
||
|
for child in tree:
|
||
|
self._ConvertElementTreeToMember(child)
|
||
|
for attribute, value in tree.attrib.iteritems():
|
||
|
self._ConvertElementAttributeToMember(attribute, value)
|
||
|
# Encode the text string according to the desired encoding type. (UTF-8)
|
||
|
if tree.text:
|
||
|
if MEMBER_STRING_ENCODING is unicode:
|
||
|
self.text = tree.text
|
||
|
else:
|
||
|
self.text = tree.text.encode(MEMBER_STRING_ENCODING)
|
||
|
|
||
|
def _ConvertElementTreeToMember(self, child_tree, current_class=None):
|
||
|
self.extension_elements.append(_ExtensionElementFromElementTree(
|
||
|
child_tree))
|
||
|
|
||
|
def _ConvertElementAttributeToMember(self, attribute, value):
|
||
|
# Encode the attribute value's string with the desired type Default UTF-8
|
||
|
if value:
|
||
|
if MEMBER_STRING_ENCODING is unicode:
|
||
|
self.extension_attributes[attribute] = value
|
||
|
else:
|
||
|
self.extension_attributes[attribute] = value.encode(
|
||
|
MEMBER_STRING_ENCODING)
|
||
|
|
||
|
# One method to create an ElementTree from an object
|
||
|
def _AddMembersToElementTree(self, tree):
|
||
|
for child in self.extension_elements:
|
||
|
child._BecomeChildElement(tree)
|
||
|
for attribute, value in self.extension_attributes.iteritems():
|
||
|
if value:
|
||
|
if isinstance(value, unicode) or MEMBER_STRING_ENCODING is unicode:
|
||
|
tree.attrib[attribute] = value
|
||
|
else:
|
||
|
# Decode the value from the desired encoding (default UTF-8).
|
||
|
tree.attrib[attribute] = value.decode(MEMBER_STRING_ENCODING)
|
||
|
if self.text:
|
||
|
if isinstance(self.text, unicode) or MEMBER_STRING_ENCODING is unicode:
|
||
|
tree.text = self.text
|
||
|
else:
|
||
|
tree.text = self.text.decode(MEMBER_STRING_ENCODING)
|
||
|
|
||
|
def FindExtensions(self, tag=None, namespace=None):
|
||
|
"""Searches extension elements for child nodes with the desired name.
|
||
|
|
||
|
Returns a list of extension elements within this object whose tag
|
||
|
and/or namespace match those passed in. To find all extensions in
|
||
|
a particular namespace, specify the namespace but not the tag name.
|
||
|
If you specify only the tag, the result list may contain extension
|
||
|
elements in multiple namespaces.
|
||
|
|
||
|
Args:
|
||
|
tag: str (optional) The desired tag
|
||
|
namespace: str (optional) The desired namespace
|
||
|
|
||
|
Returns:
|
||
|
A list of elements whose tag and/or namespace match the parameters
|
||
|
values
|
||
|
"""
|
||
|
|
||
|
results = []
|
||
|
|
||
|
if tag and namespace:
|
||
|
for element in self.extension_elements:
|
||
|
if element.tag == tag and element.namespace == namespace:
|
||
|
results.append(element)
|
||
|
elif tag and not namespace:
|
||
|
for element in self.extension_elements:
|
||
|
if element.tag == tag:
|
||
|
results.append(element)
|
||
|
elif namespace and not tag:
|
||
|
for element in self.extension_elements:
|
||
|
if element.namespace == namespace:
|
||
|
results.append(element)
|
||
|
else:
|
||
|
for element in self.extension_elements:
|
||
|
results.append(element)
|
||
|
|
||
|
return results
|
||
|
|
||
|
|
||
|
class AtomBase(ExtensionContainer):
|
||
|
|
||
|
_children = {}
|
||
|
_attributes = {}
|
||
|
|
||
|
def __init__(self, extension_elements=None, extension_attributes=None,
|
||
|
text=None):
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
self.text = text
|
||
|
|
||
|
__init__ = v1_deprecated(
|
||
|
'Please use data model classes in atom.data instead.')(
|
||
|
__init__)
|
||
|
|
||
|
def _ConvertElementTreeToMember(self, child_tree):
|
||
|
# Find the element's tag in this class's list of child members
|
||
|
if self.__class__._children.has_key(child_tree.tag):
|
||
|
member_name = self.__class__._children[child_tree.tag][0]
|
||
|
member_class = self.__class__._children[child_tree.tag][1]
|
||
|
# If the class member is supposed to contain a list, make sure the
|
||
|
# matching member is set to a list, then append the new member
|
||
|
# instance to the list.
|
||
|
if isinstance(member_class, list):
|
||
|
if getattr(self, member_name) is None:
|
||
|
setattr(self, member_name, [])
|
||
|
getattr(self, member_name).append(_CreateClassFromElementTree(
|
||
|
member_class[0], child_tree))
|
||
|
else:
|
||
|
setattr(self, member_name,
|
||
|
_CreateClassFromElementTree(member_class, child_tree))
|
||
|
else:
|
||
|
ExtensionContainer._ConvertElementTreeToMember(self, child_tree)
|
||
|
|
||
|
def _ConvertElementAttributeToMember(self, attribute, value):
|
||
|
# Find the attribute in this class's list of attributes.
|
||
|
if self.__class__._attributes.has_key(attribute):
|
||
|
# Find the member of this class which corresponds to the XML attribute
|
||
|
# (lookup in current_class._attributes) and set this member to the
|
||
|
# desired value (using self.__dict__).
|
||
|
if value:
|
||
|
# Encode the string to capture non-ascii characters (default UTF-8)
|
||
|
if MEMBER_STRING_ENCODING is unicode:
|
||
|
setattr(self, self.__class__._attributes[attribute], value)
|
||
|
else:
|
||
|
setattr(self, self.__class__._attributes[attribute],
|
||
|
value.encode(MEMBER_STRING_ENCODING))
|
||
|
else:
|
||
|
ExtensionContainer._ConvertElementAttributeToMember(
|
||
|
self, attribute, value)
|
||
|
|
||
|
# Three methods to create an ElementTree from an object
|
||
|
def _AddMembersToElementTree(self, tree):
|
||
|
# Convert the members of this class which are XML child nodes.
|
||
|
# This uses the class's _children dictionary to find the members which
|
||
|
# should become XML child nodes.
|
||
|
member_node_names = [values[0] for tag, values in
|
||
|
self.__class__._children.iteritems()]
|
||
|
for member_name in member_node_names:
|
||
|
member = getattr(self, member_name)
|
||
|
if member is None:
|
||
|
pass
|
||
|
elif isinstance(member, list):
|
||
|
for instance in member:
|
||
|
instance._BecomeChildElement(tree)
|
||
|
else:
|
||
|
member._BecomeChildElement(tree)
|
||
|
# Convert the members of this class which are XML attributes.
|
||
|
for xml_attribute, member_name in self.__class__._attributes.iteritems():
|
||
|
member = getattr(self, member_name)
|
||
|
if member is not None:
|
||
|
if isinstance(member, unicode) or MEMBER_STRING_ENCODING is unicode:
|
||
|
tree.attrib[xml_attribute] = member
|
||
|
else:
|
||
|
tree.attrib[xml_attribute] = member.decode(MEMBER_STRING_ENCODING)
|
||
|
# Lastly, call the ExtensionContainers's _AddMembersToElementTree to
|
||
|
# convert any extension attributes.
|
||
|
ExtensionContainer._AddMembersToElementTree(self, tree)
|
||
|
|
||
|
|
||
|
def _BecomeChildElement(self, tree):
|
||
|
"""
|
||
|
|
||
|
Note: Only for use with classes that have a _tag and _namespace class
|
||
|
member. It is in AtomBase so that it can be inherited but it should
|
||
|
not be called on instances of AtomBase.
|
||
|
|
||
|
"""
|
||
|
new_child = ElementTree.Element('')
|
||
|
tree.append(new_child)
|
||
|
new_child.tag = '{%s}%s' % (self.__class__._namespace,
|
||
|
self.__class__._tag)
|
||
|
self._AddMembersToElementTree(new_child)
|
||
|
|
||
|
def _ToElementTree(self):
|
||
|
"""
|
||
|
|
||
|
Note, this method is designed to be used only with classes that have a
|
||
|
_tag and _namespace. It is placed in AtomBase for inheritance but should
|
||
|
not be called on this class.
|
||
|
|
||
|
"""
|
||
|
new_tree = ElementTree.Element('{%s}%s' % (self.__class__._namespace,
|
||
|
self.__class__._tag))
|
||
|
self._AddMembersToElementTree(new_tree)
|
||
|
return new_tree
|
||
|
|
||
|
def ToString(self, string_encoding='UTF-8'):
|
||
|
"""Converts the Atom object to a string containing XML."""
|
||
|
return ElementTree.tostring(self._ToElementTree(), encoding=string_encoding)
|
||
|
|
||
|
def __str__(self):
|
||
|
return self.ToString()
|
||
|
|
||
|
|
||
|
class Name(AtomBase):
|
||
|
"""The atom:name element"""
|
||
|
|
||
|
_tag = 'name'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Name
|
||
|
|
||
|
Args:
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def NameFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Name, xml_string)
|
||
|
|
||
|
|
||
|
class Email(AtomBase):
|
||
|
"""The atom:email element"""
|
||
|
|
||
|
_tag = 'email'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Email
|
||
|
|
||
|
Args:
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
text: str The text data in the this element
|
||
|
"""
|
||
|
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def EmailFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Email, xml_string)
|
||
|
|
||
|
|
||
|
class Uri(AtomBase):
|
||
|
"""The atom:uri element"""
|
||
|
|
||
|
_tag = 'uri'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Uri
|
||
|
|
||
|
Args:
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
text: str The text data in the this element
|
||
|
"""
|
||
|
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def UriFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Uri, xml_string)
|
||
|
|
||
|
|
||
|
class Person(AtomBase):
|
||
|
"""A foundation class from 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.
|
||
|
"""
|
||
|
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
_children['{%s}name' % (ATOM_NAMESPACE)] = ('name', Name)
|
||
|
_children['{%s}email' % (ATOM_NAMESPACE)] = ('email', Email)
|
||
|
_children['{%s}uri' % (ATOM_NAMESPACE)] = ('uri', Uri)
|
||
|
|
||
|
def __init__(self, name=None, email=None, uri=None,
|
||
|
extension_elements=None, extension_attributes=None, text=None):
|
||
|
"""Foundation from which author and contributor are derived.
|
||
|
|
||
|
The constructor is provided for illustrative purposes, you should not
|
||
|
need to instantiate a Person.
|
||
|
|
||
|
Args:
|
||
|
name: Name The person's name
|
||
|
email: Email The person's email address
|
||
|
uri: Uri The URI of the person's webpage
|
||
|
extension_elements: list A list of ExtensionElement instances which are
|
||
|
children of this element.
|
||
|
extension_attributes: dict A dictionary of strings which are the values
|
||
|
for additional XML attributes of this element.
|
||
|
text: String The text contents of the element. This is the contents
|
||
|
of the Entry's XML text node. (Example: <foo>This is the text</foo>)
|
||
|
"""
|
||
|
|
||
|
self.name = name
|
||
|
self.email = email
|
||
|
self.uri = uri
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
self.text = text
|
||
|
|
||
|
|
||
|
class Author(Person):
|
||
|
"""The atom:author element
|
||
|
|
||
|
An author is a required element in Feed.
|
||
|
"""
|
||
|
|
||
|
_tag = 'author'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Person._children.copy()
|
||
|
_attributes = Person._attributes.copy()
|
||
|
#_children = {}
|
||
|
#_attributes = {}
|
||
|
|
||
|
def __init__(self, name=None, email=None, uri=None,
|
||
|
extension_elements=None, extension_attributes=None, text=None):
|
||
|
"""Constructor for Author
|
||
|
|
||
|
Args:
|
||
|
name: Name
|
||
|
email: Email
|
||
|
uri: Uri
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
text: str The text data in the this element
|
||
|
"""
|
||
|
|
||
|
self.name = name
|
||
|
self.email = email
|
||
|
self.uri = uri
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
self.text = text
|
||
|
|
||
|
|
||
|
def AuthorFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Author, xml_string)
|
||
|
|
||
|
|
||
|
class Contributor(Person):
|
||
|
"""The atom:contributor element"""
|
||
|
|
||
|
_tag = 'contributor'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Person._children.copy()
|
||
|
_attributes = Person._attributes.copy()
|
||
|
|
||
|
def __init__(self, name=None, email=None, uri=None,
|
||
|
extension_elements=None, extension_attributes=None, text=None):
|
||
|
"""Constructor for Contributor
|
||
|
|
||
|
Args:
|
||
|
name: Name
|
||
|
email: Email
|
||
|
uri: Uri
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
text: str The text data in the this element
|
||
|
"""
|
||
|
|
||
|
self.name = name
|
||
|
self.email = email
|
||
|
self.uri = uri
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
self.text = text
|
||
|
|
||
|
|
||
|
def ContributorFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Contributor, xml_string)
|
||
|
|
||
|
|
||
|
class Link(AtomBase):
|
||
|
"""The atom:link element"""
|
||
|
|
||
|
_tag = 'link'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
_attributes['rel'] = 'rel'
|
||
|
_attributes['href'] = 'href'
|
||
|
_attributes['type'] = 'type'
|
||
|
_attributes['title'] = 'title'
|
||
|
_attributes['length'] = 'length'
|
||
|
_attributes['hreflang'] = 'hreflang'
|
||
|
|
||
|
def __init__(self, href=None, rel=None, link_type=None, hreflang=None,
|
||
|
title=None, length=None, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Link
|
||
|
|
||
|
Args:
|
||
|
href: string The href attribute of the link
|
||
|
rel: string
|
||
|
type: string
|
||
|
hreflang: string The language for the href
|
||
|
title: string
|
||
|
length: string The length of the href's destination
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
text: str The text data in the this element
|
||
|
"""
|
||
|
|
||
|
self.href = href
|
||
|
self.rel = rel
|
||
|
self.type = link_type
|
||
|
self.hreflang = hreflang
|
||
|
self.title = title
|
||
|
self.length = length
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def LinkFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Link, xml_string)
|
||
|
|
||
|
|
||
|
class Generator(AtomBase):
|
||
|
"""The atom:generator element"""
|
||
|
|
||
|
_tag = 'generator'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
_attributes['uri'] = 'uri'
|
||
|
_attributes['version'] = 'version'
|
||
|
|
||
|
def __init__(self, uri=None, version=None, text=None,
|
||
|
extension_elements=None, extension_attributes=None):
|
||
|
"""Constructor for Generator
|
||
|
|
||
|
Args:
|
||
|
uri: string
|
||
|
version: string
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.uri = uri
|
||
|
self.version = version
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
def GeneratorFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Generator, xml_string)
|
||
|
|
||
|
|
||
|
class Text(AtomBase):
|
||
|
"""A foundation class from which atom:title, summary, etc. extend.
|
||
|
|
||
|
This class should never be instantiated.
|
||
|
"""
|
||
|
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
_attributes['type'] = 'type'
|
||
|
|
||
|
def __init__(self, text_type=None, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Text
|
||
|
|
||
|
Args:
|
||
|
text_type: string
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.type = text_type
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
class Title(Text):
|
||
|
"""The atom:title element"""
|
||
|
|
||
|
_tag = 'title'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Text._children.copy()
|
||
|
_attributes = Text._attributes.copy()
|
||
|
|
||
|
def __init__(self, title_type=None, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Title
|
||
|
|
||
|
Args:
|
||
|
title_type: string
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.type = title_type
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def TitleFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Title, xml_string)
|
||
|
|
||
|
|
||
|
class Subtitle(Text):
|
||
|
"""The atom:subtitle element"""
|
||
|
|
||
|
_tag = 'subtitle'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Text._children.copy()
|
||
|
_attributes = Text._attributes.copy()
|
||
|
|
||
|
def __init__(self, subtitle_type=None, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Subtitle
|
||
|
|
||
|
Args:
|
||
|
subtitle_type: string
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.type = subtitle_type
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def SubtitleFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Subtitle, xml_string)
|
||
|
|
||
|
|
||
|
class Rights(Text):
|
||
|
"""The atom:rights element"""
|
||
|
|
||
|
_tag = 'rights'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Text._children.copy()
|
||
|
_attributes = Text._attributes.copy()
|
||
|
|
||
|
def __init__(self, rights_type=None, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Rights
|
||
|
|
||
|
Args:
|
||
|
rights_type: string
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.type = rights_type
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def RightsFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Rights, xml_string)
|
||
|
|
||
|
|
||
|
class Summary(Text):
|
||
|
"""The atom:summary element"""
|
||
|
|
||
|
_tag = 'summary'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Text._children.copy()
|
||
|
_attributes = Text._attributes.copy()
|
||
|
|
||
|
def __init__(self, summary_type=None, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Summary
|
||
|
|
||
|
Args:
|
||
|
summary_type: string
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.type = summary_type
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def SummaryFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Summary, xml_string)
|
||
|
|
||
|
|
||
|
class Content(Text):
|
||
|
"""The atom:content element"""
|
||
|
|
||
|
_tag = 'content'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Text._children.copy()
|
||
|
_attributes = Text._attributes.copy()
|
||
|
_attributes['src'] = 'src'
|
||
|
|
||
|
def __init__(self, content_type=None, src=None, text=None,
|
||
|
extension_elements=None, extension_attributes=None):
|
||
|
"""Constructor for Content
|
||
|
|
||
|
Args:
|
||
|
content_type: string
|
||
|
src: string
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.type = content_type
|
||
|
self.src = src
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
def ContentFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Content, xml_string)
|
||
|
|
||
|
|
||
|
class Category(AtomBase):
|
||
|
"""The atom:category element"""
|
||
|
|
||
|
_tag = 'category'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
_attributes['term'] = 'term'
|
||
|
_attributes['scheme'] = 'scheme'
|
||
|
_attributes['label'] = 'label'
|
||
|
|
||
|
def __init__(self, term=None, scheme=None, label=None, text=None,
|
||
|
extension_elements=None, extension_attributes=None):
|
||
|
"""Constructor for Category
|
||
|
|
||
|
Args:
|
||
|
term: str
|
||
|
scheme: str
|
||
|
label: str
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.term = term
|
||
|
self.scheme = scheme
|
||
|
self.label = label
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def CategoryFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Category, xml_string)
|
||
|
|
||
|
|
||
|
class Id(AtomBase):
|
||
|
"""The atom:id element."""
|
||
|
|
||
|
_tag = 'id'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Id
|
||
|
|
||
|
Args:
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def IdFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Id, xml_string)
|
||
|
|
||
|
|
||
|
class Icon(AtomBase):
|
||
|
"""The atom:icon element."""
|
||
|
|
||
|
_tag = 'icon'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Icon
|
||
|
|
||
|
Args:
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def IconFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Icon, xml_string)
|
||
|
|
||
|
|
||
|
class Logo(AtomBase):
|
||
|
"""The atom:logo element."""
|
||
|
|
||
|
_tag = 'logo'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Logo
|
||
|
|
||
|
Args:
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def LogoFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Logo, xml_string)
|
||
|
|
||
|
|
||
|
class Draft(AtomBase):
|
||
|
"""The app:draft element which indicates if this entry should be public."""
|
||
|
|
||
|
_tag = 'draft'
|
||
|
_namespace = APP_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for app:draft
|
||
|
|
||
|
Args:
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def DraftFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Draft, xml_string)
|
||
|
|
||
|
|
||
|
class Control(AtomBase):
|
||
|
"""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.
|
||
|
"""
|
||
|
|
||
|
_tag = 'control'
|
||
|
_namespace = APP_NAMESPACE
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
_children['{%s}draft' % APP_NAMESPACE] = ('draft', Draft)
|
||
|
|
||
|
def __init__(self, draft=None, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for app:control"""
|
||
|
|
||
|
self.draft = draft
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def ControlFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Control, xml_string)
|
||
|
|
||
|
|
||
|
class Date(AtomBase):
|
||
|
"""A parent class for atom:updated, published, etc."""
|
||
|
|
||
|
#TODO Add text to and from time conversion methods to allow users to set
|
||
|
# the contents of a Date to a python DateTime object.
|
||
|
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
class Updated(Date):
|
||
|
"""The atom:updated element."""
|
||
|
|
||
|
_tag = 'updated'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Date._children.copy()
|
||
|
_attributes = Date._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Updated
|
||
|
|
||
|
Args:
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def UpdatedFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Updated, xml_string)
|
||
|
|
||
|
|
||
|
class Published(Date):
|
||
|
"""The atom:published element."""
|
||
|
|
||
|
_tag = 'published'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Date._children.copy()
|
||
|
_attributes = Date._attributes.copy()
|
||
|
|
||
|
def __init__(self, text=None, extension_elements=None,
|
||
|
extension_attributes=None):
|
||
|
"""Constructor for Published
|
||
|
|
||
|
Args:
|
||
|
text: str The text data in the this element
|
||
|
extension_elements: list A list of ExtensionElement instances
|
||
|
extension_attributes: dict A dictionary of attribute value string pairs
|
||
|
"""
|
||
|
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def PublishedFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Published, xml_string)
|
||
|
|
||
|
|
||
|
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 GetSelfLink(self):
|
||
|
"""Find the first link with rel set to 'self'
|
||
|
|
||
|
Returns:
|
||
|
An atom.Link or none if none of the links had rel equal to 'self'
|
||
|
"""
|
||
|
|
||
|
for a_link in self.link:
|
||
|
if a_link.rel == 'self':
|
||
|
return a_link
|
||
|
return None
|
||
|
|
||
|
def GetEditLink(self):
|
||
|
for a_link in self.link:
|
||
|
if a_link.rel == 'edit':
|
||
|
return a_link
|
||
|
return None
|
||
|
|
||
|
def GetEditMediaLink(self):
|
||
|
for a_link in self.link:
|
||
|
if a_link.rel == 'edit-media':
|
||
|
return a_link
|
||
|
return None
|
||
|
|
||
|
def GetNextLink(self):
|
||
|
for a_link in self.link:
|
||
|
if a_link.rel == 'next':
|
||
|
return a_link
|
||
|
return None
|
||
|
|
||
|
def GetLicenseLink(self):
|
||
|
for a_link in self.link:
|
||
|
if a_link.rel == 'license':
|
||
|
return a_link
|
||
|
return None
|
||
|
|
||
|
def GetAlternateLink(self):
|
||
|
for a_link in self.link:
|
||
|
if a_link.rel == 'alternate':
|
||
|
return a_link
|
||
|
return None
|
||
|
|
||
|
|
||
|
class FeedEntryParent(AtomBase, LinkFinder):
|
||
|
"""A super class for atom:feed and entry, contains shared attributes"""
|
||
|
|
||
|
_children = AtomBase._children.copy()
|
||
|
_attributes = AtomBase._attributes.copy()
|
||
|
_children['{%s}author' % ATOM_NAMESPACE] = ('author', [Author])
|
||
|
_children['{%s}category' % ATOM_NAMESPACE] = ('category', [Category])
|
||
|
_children['{%s}contributor' % ATOM_NAMESPACE] = ('contributor', [Contributor])
|
||
|
_children['{%s}id' % ATOM_NAMESPACE] = ('id', Id)
|
||
|
_children['{%s}link' % ATOM_NAMESPACE] = ('link', [Link])
|
||
|
_children['{%s}rights' % ATOM_NAMESPACE] = ('rights', Rights)
|
||
|
_children['{%s}title' % ATOM_NAMESPACE] = ('title', Title)
|
||
|
_children['{%s}updated' % ATOM_NAMESPACE] = ('updated', Updated)
|
||
|
|
||
|
def __init__(self, author=None, category=None, contributor=None,
|
||
|
atom_id=None, link=None, rights=None, title=None, updated=None,
|
||
|
text=None, extension_elements=None, extension_attributes=None):
|
||
|
self.author = author or []
|
||
|
self.category = category or []
|
||
|
self.contributor = contributor or []
|
||
|
self.id = atom_id
|
||
|
self.link = link or []
|
||
|
self.rights = rights
|
||
|
self.title = title
|
||
|
self.updated = updated
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
class Source(FeedEntryParent):
|
||
|
"""The atom:source element"""
|
||
|
|
||
|
_tag = 'source'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = FeedEntryParent._children.copy()
|
||
|
_attributes = FeedEntryParent._attributes.copy()
|
||
|
_children['{%s}generator' % ATOM_NAMESPACE] = ('generator', Generator)
|
||
|
_children['{%s}icon' % ATOM_NAMESPACE] = ('icon', Icon)
|
||
|
_children['{%s}logo' % ATOM_NAMESPACE] = ('logo', Logo)
|
||
|
_children['{%s}subtitle' % ATOM_NAMESPACE] = ('subtitle', Subtitle)
|
||
|
|
||
|
def __init__(self, author=None, category=None, contributor=None,
|
||
|
generator=None, icon=None, atom_id=None, link=None, logo=None,
|
||
|
rights=None, subtitle=None, title=None, updated=None, text=None,
|
||
|
extension_elements=None, extension_attributes=None):
|
||
|
"""Constructor for Source
|
||
|
|
||
|
Args:
|
||
|
author: list (optional) A list of Author instances which belong to this
|
||
|
class.
|
||
|
category: list (optional) A list of Category instances
|
||
|
contributor: list (optional) A list on Contributor instances
|
||
|
generator: Generator (optional)
|
||
|
icon: Icon (optional)
|
||
|
id: Id (optional) The entry's Id element
|
||
|
link: list (optional) A list of Link instances
|
||
|
logo: Logo (optional)
|
||
|
rights: Rights (optional) The entry's Rights element
|
||
|
subtitle: Subtitle (optional) The entry's subtitle element
|
||
|
title: Title (optional) the entry's title element
|
||
|
updated: Updated (optional) the entry's updated element
|
||
|
text: String (optional) The text contents of the element. This is the
|
||
|
contents of the Entry's XML text node.
|
||
|
(Example: <foo>This is the text</foo>)
|
||
|
extension_elements: list (optional) A list of ExtensionElement instances
|
||
|
which are children of this element.
|
||
|
extension_attributes: dict (optional) A dictionary of strings which are
|
||
|
the values for additional XML attributes of this element.
|
||
|
"""
|
||
|
|
||
|
self.author = author or []
|
||
|
self.category = category or []
|
||
|
self.contributor = contributor or []
|
||
|
self.generator = generator
|
||
|
self.icon = icon
|
||
|
self.id = atom_id
|
||
|
self.link = link or []
|
||
|
self.logo = logo
|
||
|
self.rights = rights
|
||
|
self.subtitle = subtitle
|
||
|
self.title = title
|
||
|
self.updated = updated
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
|
||
|
def SourceFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Source, xml_string)
|
||
|
|
||
|
|
||
|
class Entry(FeedEntryParent):
|
||
|
"""The atom:entry element"""
|
||
|
|
||
|
_tag = 'entry'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = FeedEntryParent._children.copy()
|
||
|
_attributes = FeedEntryParent._attributes.copy()
|
||
|
_children['{%s}content' % ATOM_NAMESPACE] = ('content', Content)
|
||
|
_children['{%s}published' % ATOM_NAMESPACE] = ('published', Published)
|
||
|
_children['{%s}source' % ATOM_NAMESPACE] = ('source', Source)
|
||
|
_children['{%s}summary' % ATOM_NAMESPACE] = ('summary', Summary)
|
||
|
_children['{%s}control' % APP_NAMESPACE] = ('control', Control)
|
||
|
|
||
|
def __init__(self, author=None, category=None, content=None,
|
||
|
contributor=None, atom_id=None, link=None, published=None, rights=None,
|
||
|
source=None, summary=None, control=None, title=None, updated=None,
|
||
|
extension_elements=None, extension_attributes=None, text=None):
|
||
|
"""Constructor for atom:entry
|
||
|
|
||
|
Args:
|
||
|
author: list A list of Author instances which belong to this class.
|
||
|
category: list A list of Category instances
|
||
|
content: Content The entry's Content
|
||
|
contributor: list A list on Contributor instances
|
||
|
id: Id The entry's Id element
|
||
|
link: list A list of Link instances
|
||
|
published: Published The entry's Published element
|
||
|
rights: Rights The entry's Rights element
|
||
|
source: Source the entry's source element
|
||
|
summary: Summary the entry's summary element
|
||
|
title: Title the entry's title element
|
||
|
updated: Updated the entry's updated element
|
||
|
control: The entry's app:control element which can be used to mark an
|
||
|
entry as a draft which should not be publicly viewable.
|
||
|
text: String The text contents of the element. This is the contents
|
||
|
of the Entry's XML text node. (Example: <foo>This is the text</foo>)
|
||
|
extension_elements: list A list of ExtensionElement instances which are
|
||
|
children of this element.
|
||
|
extension_attributes: dict A dictionary of strings which are the values
|
||
|
for additional XML attributes of this element.
|
||
|
"""
|
||
|
|
||
|
self.author = author or []
|
||
|
self.category = category or []
|
||
|
self.content = content
|
||
|
self.contributor = contributor or []
|
||
|
self.id = atom_id
|
||
|
self.link = link or []
|
||
|
self.published = published
|
||
|
self.rights = rights
|
||
|
self.source = source
|
||
|
self.summary = summary
|
||
|
self.title = title
|
||
|
self.updated = updated
|
||
|
self.control = control
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
__init__ = v1_deprecated('Please use atom.data.Entry instead.')(__init__)
|
||
|
|
||
|
|
||
|
def EntryFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Entry, xml_string)
|
||
|
|
||
|
|
||
|
class Feed(Source):
|
||
|
"""The atom:feed element"""
|
||
|
|
||
|
_tag = 'feed'
|
||
|
_namespace = ATOM_NAMESPACE
|
||
|
_children = Source._children.copy()
|
||
|
_attributes = Source._attributes.copy()
|
||
|
_children['{%s}entry' % ATOM_NAMESPACE] = ('entry', [Entry])
|
||
|
|
||
|
def __init__(self, author=None, category=None, contributor=None,
|
||
|
generator=None, icon=None, atom_id=None, link=None, logo=None,
|
||
|
rights=None, subtitle=None, title=None, updated=None, entry=None,
|
||
|
text=None, extension_elements=None, extension_attributes=None):
|
||
|
"""Constructor for Source
|
||
|
|
||
|
Args:
|
||
|
author: list (optional) A list of Author instances which belong to this
|
||
|
class.
|
||
|
category: list (optional) A list of Category instances
|
||
|
contributor: list (optional) A list on Contributor instances
|
||
|
generator: Generator (optional)
|
||
|
icon: Icon (optional)
|
||
|
id: Id (optional) The entry's Id element
|
||
|
link: list (optional) A list of Link instances
|
||
|
logo: Logo (optional)
|
||
|
rights: Rights (optional) The entry's Rights element
|
||
|
subtitle: Subtitle (optional) The entry's subtitle element
|
||
|
title: Title (optional) the entry's title element
|
||
|
updated: Updated (optional) the entry's updated element
|
||
|
entry: list (optional) A list of the Entry instances contained in the
|
||
|
feed.
|
||
|
text: String (optional) The text contents of the element. This is the
|
||
|
contents of the Entry's XML text node.
|
||
|
(Example: <foo>This is the text</foo>)
|
||
|
extension_elements: list (optional) A list of ExtensionElement instances
|
||
|
which are children of this element.
|
||
|
extension_attributes: dict (optional) A dictionary of strings which are
|
||
|
the values for additional XML attributes of this element.
|
||
|
"""
|
||
|
|
||
|
self.author = author or []
|
||
|
self.category = category or []
|
||
|
self.contributor = contributor or []
|
||
|
self.generator = generator
|
||
|
self.icon = icon
|
||
|
self.id = atom_id
|
||
|
self.link = link or []
|
||
|
self.logo = logo
|
||
|
self.rights = rights
|
||
|
self.subtitle = subtitle
|
||
|
self.title = title
|
||
|
self.updated = updated
|
||
|
self.entry = entry or []
|
||
|
self.text = text
|
||
|
self.extension_elements = extension_elements or []
|
||
|
self.extension_attributes = extension_attributes or {}
|
||
|
|
||
|
__init__ = v1_deprecated('Please use atom.data.Feed instead.')(__init__)
|
||
|
|
||
|
|
||
|
def FeedFromString(xml_string):
|
||
|
return CreateClassFromXMLString(Feed, xml_string)
|
||
|
|
||
|
|
||
|
class ExtensionElement(object):
|
||
|
"""Represents extra XML elements contained in Atom classes."""
|
||
|
|
||
|
def __init__(self, tag, namespace=None, attributes=None,
|
||
|
children=None, text=None):
|
||
|
"""Constructor for EtensionElement
|
||
|
|
||
|
Args:
|
||
|
namespace: string (optional) The XML namespace for this element.
|
||
|
tag: string (optional) The tag (without the namespace qualifier) for
|
||
|
this element. To reconstruct the full qualified name of the element,
|
||
|
combine this tag with the namespace.
|
||
|
attributes: dict (optinal) The attribute value string pairs for the XML
|
||
|
attributes of this element.
|
||
|
children: list (optional) A list of ExtensionElements which represent
|
||
|
the XML child nodes of this element.
|
||
|
"""
|
||
|
|
||
|
self.namespace = namespace
|
||
|
self.tag = tag
|
||
|
self.attributes = attributes or {}
|
||
|
self.children = children or []
|
||
|
self.text = text
|
||
|
|
||
|
def ToString(self):
|
||
|
element_tree = self._TransferToElementTree(ElementTree.Element(''))
|
||
|
return ElementTree.tostring(element_tree, encoding="UTF-8")
|
||
|
|
||
|
def _TransferToElementTree(self, element_tree):
|
||
|
if self.tag is None:
|
||
|
return None
|
||
|
|
||
|
if self.namespace is not None:
|
||
|
element_tree.tag = '{%s}%s' % (self.namespace, self.tag)
|
||
|
else:
|
||
|
element_tree.tag = self.tag
|
||
|
|
||
|
for key, value in self.attributes.iteritems():
|
||
|
element_tree.attrib[key] = value
|
||
|
|
||
|
for child in self.children:
|
||
|
child._BecomeChildElement(element_tree)
|
||
|
|
||
|
element_tree.text = self.text
|
||
|
|
||
|
return element_tree
|
||
|
|
||
|
def _BecomeChildElement(self, element_tree):
|
||
|
"""Converts this object into an etree element and adds it as a child node.
|
||
|
|
||
|
Adds self to the ElementTree. This method is required to avoid verbose XML
|
||
|
which constantly redefines the namespace.
|
||
|
|
||
|
Args:
|
||
|
element_tree: ElementTree._Element The element to which this object's XML
|
||
|
will be added.
|
||
|
"""
|
||
|
new_element = ElementTree.Element('')
|
||
|
element_tree.append(new_element)
|
||
|
self._TransferToElementTree(new_element)
|
||
|
|
||
|
def FindChildren(self, tag=None, namespace=None):
|
||
|
"""Searches child nodes for objects with the desired tag/namespace.
|
||
|
|
||
|
Returns a list of extension elements within this object whose tag
|
||
|
and/or namespace match those passed in. To find all children in
|
||
|
a particular namespace, specify the namespace but not the tag name.
|
||
|
If you specify only the tag, the result list may contain extension
|
||
|
elements in multiple namespaces.
|
||
|
|
||
|
Args:
|
||
|
tag: str (optional) The desired tag
|
||
|
namespace: str (optional) The desired namespace
|
||
|
|
||
|
Returns:
|
||
|
A list of elements whose tag and/or namespace match the parameters
|
||
|
values
|
||
|
"""
|
||
|
|
||
|
results = []
|
||
|
|
||
|
if tag and namespace:
|
||
|
for element in self.children:
|
||
|
if element.tag == tag and element.namespace == namespace:
|
||
|
results.append(element)
|
||
|
elif tag and not namespace:
|
||
|
for element in self.children:
|
||
|
if element.tag == tag:
|
||
|
results.append(element)
|
||
|
elif namespace and not tag:
|
||
|
for element in self.children:
|
||
|
if element.namespace == namespace:
|
||
|
results.append(element)
|
||
|
else:
|
||
|
for element in self.children:
|
||
|
results.append(element)
|
||
|
|
||
|
return results
|
||
|
|
||
|
|
||
|
def ExtensionElementFromString(xml_string):
|
||
|
element_tree = ElementTree.fromstring(xml_string)
|
||
|
return _ExtensionElementFromElementTree(element_tree)
|
||
|
|
||
|
|
||
|
def _ExtensionElementFromElementTree(element_tree):
|
||
|
element_tag = element_tree.tag
|
||
|
if '}' in element_tag:
|
||
|
namespace = element_tag[1:element_tag.index('}')]
|
||
|
tag = element_tag[element_tag.index('}')+1:]
|
||
|
else:
|
||
|
namespace = None
|
||
|
tag = element_tag
|
||
|
extension = ExtensionElement(namespace=namespace, tag=tag)
|
||
|
for key, value in element_tree.attrib.iteritems():
|
||
|
extension.attributes[key] = value
|
||
|
for child in element_tree:
|
||
|
extension.children.append(_ExtensionElementFromElementTree(child))
|
||
|
extension.text = element_tree.text
|
||
|
return extension
|
||
|
|
||
|
|
||
|
def deprecated(warning=None):
|
||
|
"""Decorator to raise warning each time the function is called.
|
||
|
|
||
|
Args:
|
||
|
warning: The warning message to be displayed as a string (optinoal).
|
||
|
"""
|
||
|
warning = warning or ''
|
||
|
# This closure is what is returned from the deprecated function.
|
||
|
def mark_deprecated(f):
|
||
|
# The deprecated_function wraps the actual call to f.
|
||
|
def deprecated_function(*args, **kwargs):
|
||
|
warnings.warn(warning, DeprecationWarning, stacklevel=2)
|
||
|
return f(*args, **kwargs)
|
||
|
# Preserve the original name to avoid masking all decorated functions as
|
||
|
# 'deprecated_function'
|
||
|
try:
|
||
|
deprecated_function.func_name = f.func_name
|
||
|
except TypeError:
|
||
|
# Setting the func_name is not allowed in Python2.3.
|
||
|
pass
|
||
|
return deprecated_function
|
||
|
return mark_deprecated
|