Commits

Vladimir Mihailenco  committed eea596d

init

  • Participants

Comments (0)

Files changed (306)

File .hg_archival.txt

+repo: 57efe8fe2c527a1dcf687757b36d18ea44b094d5
+node: 829b23a0f45eacad6e8c76457074c8012f9787b0
+branch: default
+latesttag: null
+latesttagdistance: 51
+syntax: glob
+.project
+.pydevproject
+.settings
+*~
+*.orig
+*.pyc
+*.pyo
+*.swp
+*.tmp
+_generated_media*
+desktop.ini
+settings_overrides.py
+nbproject
+django
+django_mongodb_engine
+djangotoolbox
+mediagenerator
+
+syntax:regexp
+^settings.py
+^dev_settings.py

File __init__.py

Empty file added.

File annoying/__init__.py

Empty file added.

File annoying/decorators.py

+from django.shortcuts import render_to_response
+from django import forms
+from django.template import RequestContext
+from django.db.models import signals as signalmodule
+from django.http import HttpResponse
+from django.utils import simplejson
+
+__all__ = ['render_to', 'signals', 'ajax_request', 'autostrip']
+
+
+try:
+    from functools import wraps
+except ImportError: 
+    def wraps(wrapped, assigned=('__module__', '__name__', '__doc__'),
+              updated=('__dict__',)):
+        def inner(wrapper):
+            for attr in assigned:
+                setattr(wrapper, attr, getattr(wrapped, attr))
+            for attr in updated:
+                getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
+            return wrapper
+        return inner
+
+
+def render_to(template=None, mimetype="text/html"):
+    """
+    Decorator for Django views that sends returned dict to render_to_response 
+    function.
+
+    Template name can be decorator parameter or TEMPLATE item in returned 
+    dictionary.  RequestContext always added as context instance.
+    If view doesn't return dict then decorator simply returns output.
+
+    Parameters:
+     - template: template name to use
+     - mimetype: content type to send in response headers
+
+    Examples:
+    # 1. Template name in decorator parameters
+
+    @render_to('template.html')
+    def foo(request):
+        bar = Bar.object.all()  
+        return {'bar': bar}
+
+    # equals to 
+    def foo(request):
+        bar = Bar.object.all()  
+        return render_to_response('template.html', 
+                                  {'bar': bar}, 
+                                  context_instance=RequestContext(request))
+
+
+    # 2. Template name as TEMPLATE item value in return dictionary.
+         if TEMPLATE is given then its value will have higher priority 
+         than render_to argument.
+
+    @render_to()
+    def foo(request, category):
+        template_name = '%s.html' % category
+        return {'bar': bar, 'TEMPLATE': template_name}
+    
+    #equals to
+    def foo(request, category):
+        template_name = '%s.html' % category
+        return render_to_response(template_name, 
+                                  {'bar': bar}, 
+                                  context_instance=RequestContext(request))
+
+    """
+    def renderer(function):
+        @wraps(function)
+        def wrapper(request, *args, **kwargs):
+            output = function(request, *args, **kwargs)
+            if not isinstance(output, dict):
+                return output
+            tmpl = output.pop('TEMPLATE', template)
+            return render_to_response(tmpl, output, \
+                        context_instance=RequestContext(request), mimetype=mimetype)
+        return wrapper
+    return renderer
+
+
+
+class Signals(object):
+    '''
+    Convenient wrapper for working with Django's signals (or any other
+    implementation using same API).
+
+    Example of usage::
+
+
+       # connect to registered signal
+       @signals.post_save(sender=YourModel)
+       def sighandler(instance, **kwargs):
+           pass
+
+       # connect to any signal
+       signals.register_signal(siginstance, signame) # and then as in example above
+
+       or 
+        
+       @signals(siginstance, sender=YourModel)
+       def sighandler(instance, **kwargs):
+           pass
+
+    In any case defined function will remain as is, without any changes.
+
+    (c) 2008 Alexander Solovyov, new BSD License
+    '''
+    def __init__(self):
+        self._signals = {}
+
+        # register all Django's default signals
+        for k, v in signalmodule.__dict__.iteritems():
+            # that's hardcode, but IMHO it's better than isinstance
+            if not k.startswith('__') and k != 'Signal':
+                self.register_signal(v, k)
+
+    def __getattr__(self, name):
+        return self._connect(self._signals[name])
+
+    def __call__(self, signal, **kwargs):
+        def inner(func):
+            signal.connect(func, **kwargs)
+            return func
+        return inner
+
+    def _connect(self, signal):
+        def wrapper(**kwargs):
+            return self(signal, **kwargs)
+        return wrapper
+
+    def register_signal(self, signal, name):
+        self._signals[name] = signal
+
+signals = Signals()
+
+
+
+class JsonResponse(HttpResponse):
+    """
+    HttpResponse descendant, which return response with ``application/json`` mimetype.
+    """
+    def __init__(self, data):
+        super(JsonResponse, self).__init__(content=simplejson.dumps(data), mimetype='application/json')
+
+
+
+def ajax_request(func):
+    """
+    If view returned serializable dict, returns JsonResponse with this dict as content.
+
+    example:
+        
+        @ajax_request
+        def my_view(request):
+            news = News.objects.all()
+            news_titles = [entry.title for entry in news]
+            return {'news_titles': news_titles}
+    """
+    @wraps(func)
+    def wrapper(request, *args, **kwargs):
+        response = func(request, *args, **kwargs)
+        if isinstance(response, dict):
+            return JsonResponse(response)
+        else:
+            return response
+    return wrapper
+
+
+def autostrip(cls):
+    """
+    strip text fields before validation
+
+    example:
+    class PersonForm(forms.Form):
+        name = forms.CharField(min_length=2, max_length=10)
+        email = forms.EmailField()
+
+    PersonForm = autostrip(PersonForm)
+    
+    #or you can use @autostrip in python >= 2.6
+
+    Author: nail.xx
+    """
+    fields = [(key, value) for key, value in cls.base_fields.iteritems() if isinstance(value, forms.CharField)]
+    for field_name, field_object in fields:
+        def get_clean_func(original_clean):
+            return lambda value: original_clean(value and value.strip())
+        clean_func = get_clean_func(getattr(field_object, 'clean'))
+        setattr(field_object, 'clean', clean_func)
+    return cls
+

File annoying/exceptions.py

+class Redirect(Exception):
+    def __init__(self, *args, **kwargs):
+        self.args = args
+        self.kwargs = kwargs
+

File annoying/fields.py

+from django.db import models
+from django.db.models import OneToOneField
+from django.utils import simplejson as json
+from django.core.serializers.json import DjangoJSONEncoder
+from django.db.models.fields.related import SingleRelatedObjectDescriptor
+
+
+class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
+    def __get__(self, instance, instance_type=None):
+        try:
+            return super(AutoSingleRelatedObjectDescriptor, self).__get__(instance, instance_type)
+        except self.related.model.DoesNotExist:
+            obj = self.related.model(**{self.related.field.name: instance})
+            obj.save()
+            return obj
+
+
+class AutoOneToOneField(OneToOneField):
+    '''
+    OneToOneField creates related object on first call if it doesnt exists yet.
+    Use it instead of original OneToOne field.
+
+    example:
+        
+        class MyProfile(models.Model):
+            user = AutoOneToOneField(User, primary_key=True)
+            home_page = models.URLField(max_length=255, blank=True)
+            icq = models.IntegerField(max_length=255, null=True)
+    '''
+    def contribute_to_related_class(self, cls, related):
+        setattr(cls, related.get_accessor_name(), AutoSingleRelatedObjectDescriptor(related))
+
+
+class JSONField(models.TextField):
+    """
+    JSONField is a generic textfield that neatly serializes/unserializes
+    JSON objects seamlessly.
+    Django snippet #1478
+
+    example:
+        class Page(models.Model):
+            data = JSONField(blank=True, null=True)
+
+
+        page = Page.objects.get(pk=5)
+        page.data = {'title': 'test', 'type': 3}
+        page.save()
+    """
+
+    __metaclass__ = models.SubfieldBase
+
+    def to_python(self, value):
+        if value == "":
+            return None
+
+        try:
+            if isinstance(value, basestring):
+                return json.loads(value)
+        except ValueError:
+            pass
+        return value
+
+    def get_db_prep_save(self, value):
+        if value == "":
+            return None
+        if isinstance(value, dict):
+            value = json.dumps(value, cls=DjangoJSONEncoder)
+        return super(JSONField, self).get_db_prep_save(value)
+

File annoying/functions.py

+from django.shortcuts import _get_queryset
+from django.conf import settings
+
+
+def get_object_or_None(klass, *args, **kwargs):
+    """
+    Uses get() to return an object or None if the object does not exist.
+
+    klass may be a Model, Manager, or QuerySet object. All other passed
+    arguments and keyword arguments are used in the get() query.
+
+    Note: Like with get(), an MultipleObjectsReturned will be raised if more than one
+    object is found.
+    """
+    queryset = _get_queryset(klass)
+    try:
+        return queryset.get(*args, **kwargs)
+    except queryset.model.DoesNotExist:
+        return None
+
+
+
+def get_config(key, default):
+    """
+    Get settings from django.conf if exists,
+    return default value otherwise
+
+    example:
+
+    ADMIN_EMAIL = get_config('ADMIN_EMAIL', 'default@email.com')
+    """
+    return getattr(settings, key, default)

File annoying/middlewares.py

+import re
+
+from django.conf import settings
+from django.views.static import serve
+from django.shortcuts import redirect
+
+from .exceptions import Redirect
+
+
+class StaticServe(object):
+    """
+    Django middleware for serving static files instead of using urls.py
+    """
+    regex = re.compile(r'^%s(?P<path>.*)$' % settings.MEDIA_URL)
+
+    def process_request(self, request):
+        if settings.DEBUG:
+            match = self.regex.search(request.path)
+            if match:
+                return serve(request, match.group(1), settings.MEDIA_ROOT)
+
+
+class RedirectMiddleware(object):
+    """
+    You must add this middleware to MIDDLEWARE_CLASSES list,
+    to make work Redirect exception. All arguments passed to
+    Redirect will be passed to django built in redirect function.
+    """
+    def process_exception(self, request, exception):
+        if not isinstance(exception, Redirect):
+            return
+        return redirect(*exception.args, **exception.kwargs)

File annoying/templatetags/__init__.py

Empty file added.

File annoying/templatetags/annoying.py

+import django
+from django import template
+
+from smart_if import smart_if
+
+
+register = template.Library()
+
+
+try:
+    if int(django.get_version()[-5:]) < 11806:
+        register.tag('if', smart_if)
+except ValueError:
+    pass

File annoying/templatetags/smart_if.py

+from django import template
+
+__author__ = "SmileyChris"
+
+#==============================================================================
+# Calculation objects
+#==============================================================================
+
+class BaseCalc(object):
+    def __init__(self, var1, var2=None, negate=False):
+        self.var1 = var1
+        self.var2 = var2
+        self.negate = negate
+
+    def resolve(self, context):
+        try:
+            var1, var2 = self.resolve_vars(context)
+            outcome = self.calculate(var1, var2)
+        except:
+            outcome = False
+        if self.negate:
+            return not outcome
+        return outcome
+
+    def resolve_vars(self, context):
+        var2 = self.var2 and self.var2.resolve(context)
+        return self.var1.resolve(context), var2
+
+    def calculate(self, var1, var2):
+        raise NotImplementedError()
+
+
+class Or(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 or var2
+
+
+class And(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 and var2
+
+
+class Equals(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 == var2
+
+
+class Greater(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 > var2
+
+
+class GreaterOrEqual(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 >= var2
+
+
+class In(BaseCalc):
+    def calculate(self, var1, var2):
+        return var1 in var2
+
+
+OPERATORS = {
+    '=': (Equals, True),
+    '==': (Equals, True),
+    '!=': (Equals, False),
+    '>': (Greater, True),
+    '>=': (GreaterOrEqual, True),
+    '<=': (Greater, False),
+    '<': (GreaterOrEqual, False),
+    'or': (Or, True),
+    'and': (And, True),
+    'in': (In, True),
+}
+BOOL_OPERATORS = ('or', 'and')
+
+
+class IfParser(object):
+    error_class = ValueError
+
+    def __init__(self, tokens):
+        self.tokens = tokens
+
+    def _get_tokens(self):
+        return self._tokens
+
+    def _set_tokens(self, tokens):
+        self._tokens = tokens
+        self.len = len(tokens)
+        self.pos = 0
+
+    tokens = property(_get_tokens, _set_tokens)
+
+    def parse(self):
+        if self.at_end():
+            raise self.error_class('No variables provided.')
+        var1 = self.get_bool_var()
+        while not self.at_end():
+            op, negate = self.get_operator()
+            var2 = self.get_bool_var()
+            var1 = op(var1, var2, negate=negate)
+        return var1
+
+    def get_token(self, eof_message=None, lookahead=False):
+        negate = True
+        token = None
+        pos = self.pos
+        while token is None or token == 'not':
+            if pos >= self.len:
+                if eof_message is None:
+                    raise self.error_class()
+                raise self.error_class(eof_message)
+            token = self.tokens[pos]
+            negate = not negate
+            pos += 1
+        if not lookahead:
+            self.pos = pos
+        return token, negate
+
+    def at_end(self):
+        return self.pos >= self.len
+
+    def create_var(self, value):
+        return TestVar(value)
+
+    def get_bool_var(self):
+        """
+        Returns either a variable by itself or a non-boolean operation (such as
+        ``x == 0`` or ``x < 0``).
+
+        This is needed to keep correct precedence for boolean operations (i.e.
+        ``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``).
+        """
+        var = self.get_var()
+        if not self.at_end():
+            op_token = self.get_token(lookahead=True)[0]
+            if isinstance(op_token, basestring) and (op_token not in
+                                                     BOOL_OPERATORS):
+                op, negate = self.get_operator()
+                return op(var, self.get_var(), negate=negate)
+        return var
+
+    def get_var(self):
+        token, negate = self.get_token('Reached end of statement, still '
+                                       'expecting a variable.')
+        if isinstance(token, basestring) and token in OPERATORS:
+            raise self.error_class('Expected variable, got operator (%s).' %
+                                   token)
+        var = self.create_var(token)
+        if negate:
+            return Or(var, negate=True)
+        return var
+
+    def get_operator(self):
+        token, negate = self.get_token('Reached end of statement, still '
+                                       'expecting an operator.')
+        if not isinstance(token, basestring) or token not in OPERATORS:
+            raise self.error_class('%s is not a valid operator.' % token)
+        if self.at_end():
+            raise self.error_class('No variable provided after "%s".' % token)
+        op, true = OPERATORS[token]
+        if not true:
+            negate = not negate
+        return op, negate
+
+
+#==============================================================================
+# Actual templatetag code.
+#==============================================================================
+
+class TemplateIfParser(IfParser):
+    error_class = template.TemplateSyntaxError
+
+    def __init__(self, parser, *args, **kwargs):
+        self.template_parser = parser
+        return super(TemplateIfParser, self).__init__(*args, **kwargs)
+
+    def create_var(self, value):
+        return self.template_parser.compile_filter(value)
+
+
+class SmartIfNode(template.Node):
+    def __init__(self, var, nodelist_true, nodelist_false=None):
+        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
+        self.var = var
+
+    def render(self, context):
+        if self.var.resolve(context):
+            return self.nodelist_true.render(context)
+        if self.nodelist_false:
+            return self.nodelist_false.render(context)
+        return ''
+
+    def __repr__(self):
+        return "<Smart If node>"
+
+    def __iter__(self):
+        for node in self.nodelist_true:
+            yield node
+        if self.nodelist_false:
+            for node in self.nodelist_false:
+                yield node
+
+    def get_nodes_by_type(self, nodetype):
+        nodes = []
+        if isinstance(self, nodetype):
+            nodes.append(self)
+        nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype))
+        if self.nodelist_false:
+            nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype))
+        return nodes
+
+
+def smart_if(parser, token):
+    """
+    A smarter {% if %} tag for django templates.
+
+    While retaining current Django functionality, it also handles equality,
+    greater than and less than operators. Some common case examples::
+
+        {% if articles|length >= 5 %}...{% endif %}
+        {% if "ifnotequal tag" != "beautiful" %}...{% endif %}
+
+    Arguments and operators _must_ have a space between them, so
+    ``{% if 1>2 %}`` is not a valid smart if tag.
+
+    All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``),
+    ``!=``, ``>``, ``>=``, ``<`` and ``<=``.
+    """
+    bits = token.split_contents()[1:]
+    var = TemplateIfParser(parser, bits).parse()
+    nodelist_true = parser.parse(('else', 'endif'))
+    token = parser.next_token()
+    if token.contents == 'else':
+        nodelist_false = parser.parse(('endif',))
+        parser.delete_first_token()
+    else:
+        nodelist_false = None
+    return SmartIfNode(var, nodelist_true, nodelist_false)
+

File annoying/utils.py

+from django.http import HttpResponse
+from django.utils.encoding import iri_to_uri
+
+
+class HttpResponseReload(HttpResponse):
+    """
+    Reload page and stay on the same page from where request was made.
+
+    example:
+
+    def simple_view(request):
+        if request.POST:
+            form = CommentForm(request.POST):
+            if form.is_valid():
+                form.save()
+                return HttpResponseReload(request)
+        else:
+            form = CommentForm()
+        return render_to_response('some_template.html', {'form': form})
+    """
+    status_code = 302
+
+    def __init__(self, request):
+        HttpResponse.__init__(self)
+        referer = request.META.get('HTTP_REFERER')
+        self['Location'] = iri_to_uri(referer or "/")
+application: manageyoutube
+version: 1-1
+runtime: python
+api_version: 1
+
+default_expiration: '365d'
+
+handlers:
+- url: /remote_api
+  script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
+  login: admin
+
+- url: /stats.*
+  script: $PYTHON_LIB/google/appengine/ext/appstats/ui.py
+
+- url: /_ah/queue/deferred
+  script: djangoappengine/deferred/handler.py
+  login: admin
+
+- url: /media/admin
+  static_dir: django/contrib/admin/media/
+
+- url: /static
+  static_dir: static
+
+- url: /.*
+  script: djangoappengine/main/main.py

File atom/__init__.py

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