1. Lynn Rees
  2. webstring

Commits

Lynn Rees  committed 56faa7f

- 0.5

  • Participants
  • Parent commits 35eefee
  • Branches webstring

Comments (0)

Files changed (88)

File branches/0.1/webstring.py

-#! /usr/bin/env python
-
-# Copyright (c) 2006 L. C. Rees.  All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1.  Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-# 2.  Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# 3.  Neither the name of the Portable Site Information Project nor the names
-# of its contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-# POSSIBILITY OF SUCH DAMAGE.
-
-'''webstring is an ElementTree wrapper that enables Python programmers to
-manipulate XML and HTML documents using standard Python sequence and string
-operators. It is designed for programmers whose favorite web template
-languages are Python and HTML. webstring's design is inspired by PyMeld
-(http://www.entrian.com/PyMeld/) but with a stricter Python feel. Like PyMeld,
-webstring separates the view (the XML/HTML document) from the controller
-(Python). It uses XML/HTML attributes (by default "id" and "class") to indicate
-which elements within a document are fields. webstring flattens a document into
-a Python object hierarchy, exposing only the fields. Web designers do not need
-to learn how to program since fields are marked with standard XML/HTML
-attributes. Python programmers get to use Python so they do not have to learn
-another templating language or web design.
-
-webstring requires Python 2.4, cElementTree, elementtree, and elementtidy.
-'''
-
-__author__ = 'L.C. Rees (lcreesl@gmail.com)'
-__version__ = '0.2'
-
-# Exception messages
-_exceptions = ['maximum allowed repetitions exceeded',
-    '', # removed
-    'invalid type for web formatting',
-    'not all arguments converted during web formatting',
-    'not enough arguments for web format',
-    'Requires elementtidy from http://effbot.org/downloads/',
-    'Requires cElementTree and elementtree from http://effbot.org/downloads/']
-
-# Standard library imports
-import random as _random
-import md5 as _md5
-import string as _string
-from collections import deque as _deque
-from keyword import kwlist as _kwlist
-from sys import maxint as _maxint
-from random import randint as _randint
-
-# Non-library (as of Python 2.4) imports 
-try:
-    import cElementTree as _etree
-except ImportError:
-    raise ImportError(_exceptions[6])
-
-# Illegal characters for Python objects
-_forbidden = '()[]{}@,:.`=;+-*/%&|^><\'"#\\$?!~'
-# List of Python keywords
-_keywords = frozenset(_kwlist)
-_reserved = _string.maketrans('', '')
-# Group Template types
-_groups = set(('root', 'group', 'group copy'))
-# Get random seed
-_random.seed()
-
-
-def _checkname(name):
-    '''Returns a string that works as a Python variable name
-
-    @param name String for checking for Python conformity
-    @return String legal as a Python variable name
-    '''
-    # Modify name so Pythonically illegal characters are removed
-    name = name.replace('.', '_').translate(_reserved, _forbidden)
-    # Change if name is a keyword
-    if name in _keywords:
-        return ''.join([name, '_'])
-    # Otherwise, return the name unmodified
-    else:
-        return name
-
-def _copytree(tree):
-    '''Makes a copy of an element
-    
-    @param tree Element to be copied
-    @return Element an copy of an element
-    '''
-    tnode = _etree.Element(tree.tag, dict(tree.attrib.items()))
-    tnode.tail, tappend = tree.tail, tnode.append
-    for child in tree:
-        tappend(_copytree(child))
-    return tnode
-
-
-class _Template(object):
-
-    '''Template engine for manipulating XML documents with sequence and
-    string operators.
-    '''  
-    
-    def __init__(self, src=None, parent=None, auto=True, omax=25, typ='root'):
-        '''Initialization method for _Template        
-        
-        @param src Path, string, or element source (default: None)
-        @param parent Parent element of the source (default: None)
-        @param auto Turns automagic on and off (default: True)
-        @param omax Maximum number of times a field can repeat (default: 25)
-        @param typ Type of Template an object is (default: 'root')
-        '''
-        # Structural variables
-        self._parent, self._template = parent, None
-        # Tracking data structures
-        self._children, self._siblings = list(), list()
-        self._fielddict, self._fields, self._filter = dict(), list(), set()
-        # Internal metadata
-        self.__name__, self._auto = 'root', auto
-        self.max, self._omax, self._type = omax, omax, typ
-        # Markers for fields
-        self.mark, self.groupmark = 'id', 'class'
-        # Check if the source is an element
-        if _etree.iselement(src):
-            self.tree = src
-        # Check if source exists
-        elif src is not None:
-            # Try reading source from a file
-            try:
-                open(src)
-                self.fromfile(src)
-            except IOError:
-                try:
-                    # Try parsing source as a string
-                    try:
-                        self.tree = _etree.fromstring(src)
-                    # Otherwise, try feeding it through tidy
-                    except SyntaxError:
-                        # Try importing elementtidy for interesting HTML
-                        try:
-                            from elementtidy import TidyHTMLTreeBuilder as tidy
-                        except ImportError:
-                            raise ImportError(_exceptions[5])
-                        # Feed parser
-                        parser = tidy.TreeBuilder()
-                        parser.feed(src)
-                        info = parser.close()
-                        # Get element
-                        self.tree = _etree.Element(_etree.tostring(info))
-                # Raise error if none of the above is true
-                except SyntaxError:
-                    raise TypeError('invalid source for Template class')
-
-    # Special methods                
-
-    def __repr__(self):
-        '''String representation of object.'''
-        return '<Template "%s" at %x>' % (self.__name__, id(self))
-
-    def __str__(self):
-        '''Returns a string from the parent element.'''
-        return self.render()
-
-    def __add__(self, data):
-        '''Inserts a single element or elements from another Template after
-        the internal element, resets the object, and returns a string.
-
-        @param data Template or element
-        @return String from the parent element
-        '''
-        self += data
-        return self.pipe()
-
-    def __radd__(self, data):
-        '''Same as __add__, only from the right.'''
-        self += data
-        return self.pipe()
-
-    def __iadd__(self, data):
-        '''Inserts a single element or elements from another Template after
-        the internal element and returns the modified object.
-
-        @param data Template object or element
-        @return This object
-        '''
-        # Try inserting element since most common operation
-        try:               
-            self._parent.insert(self._index, data)
-            # Add to sibling tracking list
-            self._siblings.append(data)
-        except AttributeError:            
-            try:
-                # Cache index of element if possible
-                self._index = self._parent.getchildren().index(self._tree) + 1
-                self._parent.insert(self._index, data)
-                # Add to sibling tracking list
-                self._siblings.append(data)
-            except TypeError:
-                # Check if Template instance
-                if hasattr(data, 'groupmark'):
-                    # Check if root Template
-                    if data._type == 'root':
-                        children = data._parent.getchildren()
-                        # Concatenate child elements with self
-                        for element in children:
-                            self += element
-                        # Add fields to internal field list
-                        self._fields.extend(data._fields)
-                    # Otherwise, append internal tree
-                    else:
-                        self += data._tree
-                        # Add group to internal fields
-                        self._fields.append(data)
-                # If not a template, raise TypeError
-                else:
-                    raise TypeError(_exceptions[2])
-            # If root Template, append the data
-            except ValueError:
-                self.append(data)
-        except TypeError:
-             # Check if Template instance
-            if hasattr(data, 'groupmark'):
-                # Check if root Template
-                if data._type == 'root':
-                    children = data._parent.getchildren()
-                    # Concatenate child elements with self
-                    for element in children:
-                        self += element
-                    # Add fields to internal field list
-                    self._fields.extend(data._fields)
-                # Otherwise, append internal tree
-                else:
-                    self += data._tree
-                    # Add group to internal fields
-                    self._fields.append(data)
-            # If not a template, raise TypeError
-            else:
-                raise TypeError(_exceptions[2])
-        # If root Template, append the data
-        except ValueError:
-            self.append(data)
-        return self
-
-    def __mul__(self, num):
-        '''Repeats the insertion of the internal element n times, resets the
-        object, and returns a string.
-
-        @param num Number of repetitions
-        @return String from the parent element
-        '''
-        self *= num
-        return self.pipe()
-
-    def __rmul__(self, num):
-        '''Same as __mul__, only from the right.'''
-        self *= num
-        return self.pipe()
-
-    def __imul__(self, num):
-        '''Repeats the insertion of the internal tree n times and returns the
-        object.
-
-        @param num Number of repetitions
-        @return This object
-        '''
-        # Ensure number does not exceed maximum allowed repetitions
-        if num <= self.max:
-            # Localize copy
-            ccopy = self.copy
-            # Append x number of copies of self
-            for x in range(num-1):
-                self += ccopy()
-        else:
-            raise TypeError(_exceptions[0])
-        return self
-
-    def __mod__(self, data):
-        '''Inserts data into the internal element's text attribute, resets the
-        object, and returns a string.
-
-        @param data String, list, tuple, or dictionary
-        @return String from the parent element
-        '''
-        self %= data
-        return self.pipe()
-
-    def __imod__(self, data):
-        '''Inserts data into the internal element's text attribute and modifies
-        and returns the object.
-
-        @param data String, list, tuple, or dictionary       
-        @return This object
-        '''
-        # Cache length of data and self for future comparisons
-        length, lself = len(data), len(self._fields) 
-        # Handle string data
-        if isinstance(data, basestring):
-            # Localize
-            item = self._fields[0]
-            # Don't insert into groups
-            if lself == 1 and item._type not in ('group', 'group copy'):
-                item._tree.text = data
-            # Raise TypeError if group or length > 1
-            else:
-                raise TypeError(_exceptions[3])
-        # If number of fields == number of items in sequence...
-        elif length == lself:
-            # If length does not exceed maximum allowed repetitions...
-            if length <= self.max:
-               # If data sequence is a list or tuple...
-                if isinstance(data, (list, tuple)):
-                    # Localize fields
-                    fields = self._fields
-                    # Iterate with index and item through data
-                    for key, item in enumerate(data):
-                        # If item is a string, assign to text attribute
-                        if isinstance(item, basestring):
-                            fields[key]._tree.text = item
-                        # If item is a sequence, expand it
-                        elif isinstance(item, (list, tuple, dict)):
-                            fields[key] **= item
-                        # Raise TypeError if none of the above
-                        else:
-                            raise TypeError(_exceptions[2])
-                # If data sequence is a dictionary...
-                elif isinstance(data, dict):
-                    # Localize fielddict
-                    fielddict = self._fielddict
-                    # ...iterate through items
-                    for key, item in data.iteritems():
-                        # If item is a string, assign to text attribute
-                        if isinstance(item, basestring):
-                            fielddict[key]._tree.text = item
-                        # If item is a sequence, expand it
-                        elif isinstance(item, (list, tuple, dict)):
-                            fielddict[key] **= item
-                        # Raise TypeError if none of the above
-                        else:
-                            raise TypeError(_exceptions[2])
-            # Raise TypeError if maximum allowed repetitions exceeded
-            else:
-                raise TypeError(_exceptions[0])
-        # Raise TypeError if too many items in sequence to match all fields
-        elif length > lself:
-            raise TypeError(_exceptions[3])
-        # Raise TypeError if too few items in sequence to match all fields
-        elif length < lself:
-            raise TypeError(_exceptions[4])
-        return self
-                
-    def __pow__(self, data):
-        '''For each item in a sequence, copies the internal element,
-        populates it with text from the sequence, inserts the copy after the
-        internal element, resets the object, and returns a string.
-
-        @param data List, tuple, or dictionary
-        @return String from parent element
-        '''
-        self **= data
-        return self.pipe()
-
-    def __ipow__(self, data):
-        '''For each item in a sequence, copies the internal element, populates
-        them with text from the sequence, inserts the copy after the internal
-        element, and returns the object.
-
-        @param data List, tuple, or dictionary     
-        @return This object
-        '''
-       # Ensure number does not exceed maximum allowed repetitions
-        if len(data) <= self.max:
-            # If dictionary, use only the values
-            if isinstance(data, dict):
-                data = _deque(data.values())
-            # Otherwise, deque entire sequence
-            elif isinstance(data, (tuple, list)):
-                data = _deque(data)
-            # If unsupported type, raise exception
-            else:
-                raise TypeError(_exceptions[2])
-            # Populate existing field
-            self %= data.popleft()
-            # Localize functions
-            dpop, ccopy = data.pop, self.copy
-            # Append a new field for each item in a sequence till empty
-            while data:
-                node = ccopy()
-                node %= dpop()
-                self += node
-        #Raise TypeError if data length longer than max allowed repetions
-        else:
-            raise TypeError(_exceptions[0]) 
-        return self
-
-    def __delattr__(self, attr):
-        '''Deletes Template attributes (e.g. 'del x.attr').'''
-        try:
-            # Try removing field from root Template
-            try:
-                # Delete from interal field dictionary
-                obj = self._fielddict.pop(attr)
-                # Remove internal element from parent
-                obj._parent.remove(obj.tree)
-                # Remove from internal field list
-                self._fields.remove(obj)    
-            except KeyError: pass
-        # Always perform usual deletion of object attribute
-        finally:
-            object.__delattr__(self, attr)
-
-    def __getitem__(self, key):
-        '''Returns a field at an index.'''
-        return self._fields[key]          
-    
-    def __setitem__(self, key, value):
-        '''Stub'''
-        
-    def __delitem__(self, key):
-        '''Deletes a field (e.g. del x[0]).'''
-        # Fetch object
-        obj = self._fields[key]
-        # Get object name
-        for name, element in self._fielddict.iteritems():
-            if element == obj:
-                break
-        # Delete the attribute using overridden __delattr__
-        self.__delattr__(name)
-
-    def __len__(self):
-        '''Returns the number of fields in a Template.'''
-        return len(self._fields)
-        
-    def __contains__(self, key):
-        '''Returns True or False if a field name is in a Template.'''
-        return self._fielddict.has_key(key)
-
-    def __iter__(self):
-        '''Returns iterator that goes over the internal field list.'''
-        return iter(self._fields)
-        
-    # Properties        
-    
-    def _gettext(self):
-        '''Returns the string from the internal element's text attribute.'''
-        return self._tree.text
-
-    def _settext(self, text):
-        '''Sets internal element's text attribute.'''
-        # Check if string...
-        if isinstance(text, basestring):
-            self._tree.text = text
-        # Otherwise raise TypeError
-        else:
-            raise TypeError('input must be of type string')
-
-    def _deltext(self):
-        '''Deletes text in internal element's text attribute.'''
-        self._tree.text = None
-
-    # Create text property
-    text = property(_gettext, _settext, _deltext)
-
-    def _gettemp(self):
-        '''Returns the string of the internal text template.'''
-        if self._template is not None:
-            return self._template.template
-        else: 
-            return self._template
-
-    def _settemp(self, template):
-        '''Sets the internal text template.'''
-        # Create template using STDLIB's string.Template        
-        self._template = _string.Template(template)
-
-    def _deltemp(self):
-        '''Deletes the internal text template.'''
-        self._template = None
-
-    # Create template property
-    template = property(_gettemp, _settemp, _deltemp)
-
-    def _gettree(self):
-        '''Returns the internal element object.'''
-        return self._tree
-
-    def _settree(self, tree):
-        '''Sets the internal element object.'''
-        # Set internal element and backup tree (_btree) attributes
-        self._tree, self._btree = tree, _copytree(tree)
-        self._attrib, typ = tree.attrib, self._type
-        # Handle most objects (non-groups)
-        if typ not in _groups:
-            # If field, add self to internal field trackers
-            self._fields.append(self)
-            self._fielddict[self.__name__] = self
-            # Localize
-            attrib, pclass = self._attrib, self.__class__
-            # Make object attributes from element attributes if auto on
-            if self._auto:
-                for attr in attrib:
-                    # Check name
-                    name = _checkname(attr)
-                    # Set new class as attribute of this object's superclass
-                    setattr(pclass, name, _WebAttribute(attrib, attr, name))
-        # Handle groups
-        else:            
-            # Localize
-            mark, addgroup, filter = self.mark, self._addclass, self._filter
-            auto, omax = self._auto, self.max
-            fields, fielddict = self._fields, self._fielddict
-            # Set root Template to be its own parent
-            if typ == 'root':
-                self._parent = tree
-            # Find fields in tree
-            for parent in tree.getiterator():
-                # Get child, parent pairs
-                for child in parent:
-                    # If element has mark, make field
-                    try:
-                        # Get name
-                        realname = child.attrib[mark]
-                        name = _checkname(realname)
-                        # Check if processed already
-                        if name not in filter:
-                            filter.add(name)
-                            # Make element
-                            node = Template(child, parent, auto, omax, 'field')
-                            # Add to trackers
-                            fielddict[name], node.__name__ = node, name
-                            fields.append(node)
-                            # Make field object attribute of self if auto on
-                            if auto:
-                                setattr(self, name, node)
-                    # Try making a group
-                    except (TypeError, KeyError):
-                        try:
-                            # Only process groupmarks if root Template
-                            if typ == 'root':
-                                addgroup(child, parent)
-                        except (TypeError, KeyError): pass
-
-    def _deltree(self):
-        '''Deletes the internal element'''
-        self._tree = None
-
-    # Create tree property
-    tree = property(_gettree, _settree, _deltree)
-
-    def _getovermax(self):
-        '''Returns overall maximum repetition value for all children.'''
-        return self.max
-
-    def _setovermax(self, omax):
-        '''Sets overall maximum repetition value for all children.'''
-        self.max = omax
-        # Run over fields
-        if self._type in _groups:
-            for field in self._fields:
-                field.overmax = omax
-
-    def _delovermax(self):
-        '''Sets overall maximum repetition value back to original settings.'''
-        self.max = self._omax
-        # Run over fields
-        if self._type in _groups:
-            for field in self._fields:
-                # Set to original value
-                field.overmax = self._omax
-
-    # Property for setting an overiding maximum repetition value    
-    overmax = property(_getovermax, _setovermax, _delovermax)     
-
-    # Internal methods
-
-    def _addclass(self, child, parent):
-        '''Creates Templates from groups of fields'''
-        # Localize
-        filter, addgroup, auto = self._filter, self._addclass, self._auto
-        # Get group name
-        realname = child.attrib[self.groupmark]
-        # Get Python compatible name
-        name = _checkname(realname)
-        # Check if group already processed
-        if name not in filter:
-            # Mark name as processed
-            filter.add(name)
-            # Extract any groups under this element
-            for prnt in child.getiterator():
-                for chld in prnt:
-                    try:
-                        addgroup(chld, prnt)
-                    except KeyError: pass
-            # Make new Template
-            node = Template(None, parent, auto, self.max, 'group')
-            node._filter, node.tree = self._filter, child
-            # Only add nodes with children to root Template
-            if len(node):
-                # Make group Template attribute of root Template 
-                self._fielddict[name], node.__name__ = node, name
-                self._fields.append(node)                 
-                # Make field object attribute of self if auto on
-                if auto:
-                    setattr(self, name, node)            
-
-    # "Public" methods
-
-    def append(self, data):        
-        '''Appends a single element or elements from another Template as
-        children of this object's internal element and returns the modified
-        object.
-
-        @param data Template or Element
-        '''
-        # Try appending element to tree since most common operation
-        try:
-            self._tree.append(data)
-            # Add to child tracker
-            self._children.append(data)
-        # If data is not element, try appending as a Template object
-        except TypeError:
-            if hasattr(data, 'groupmark'):
-                # Concatenate the internal parent's child elements with self
-                children, append = data._parent.getchildren(), self.append
-                for element in children:
-                    append(element)
-                # If other Template is a root Template
-                if self._type == 'root':
-                    self._fields.extend(data._fields)
-            # If not a Template object, raise TypeError
-            else:
-                raise TypeError(_exceptions[2])
-
-    def copy(self):
-        '''Returns a copy of Template object.
-
-        @return Copy of self
-        '''
-        # Copy the (unmodified) backup tree
-        cpy, typ = _copytree(self._btree), self._type
-        # Handle root copies
-        if typ == 'root':
-            node = Template(cpy, None, self._auto, self.max)
-        # Handle group copies
-        elif typ == 'group':
-            node = Template(cpy, self._parent, self._auto,
-                self.max, 'group copy')
-        # Handle other copies
-        else:
-            node = Template(cpy, self._parent, self._auto, self.max, 'copy')
-        # Name copy
-        node.__name__ = self.__name__
-        return node
-
-    def filter(self, key):
-        '''Excludes a field or group in a tree from a Template.
-
-        @param key Name of an field or group
-        '''
-        # If key is string...
-        if isinstance(key, basestring):
-            # Add to internal tracker
-            self._filter.add(key)
-            # Remove if object attribute
-            if hasattr(self, key):
-                try:
-                    self.__delattr__(key)
-                except AttributeError: pass
-        # If key is sequence...
-        elif isinstance(key, (list, tuple)):
-            # Process all keys
-            for item in key:
-                # Add to internal tracker
-                self._filter.add(item)
-                # Remove if object attribute
-                if hasattr(self, item):
-                    try:
-                        self.__delattr__(key)
-                    except AttributeError: pass
-        # Raise exception if unsupported type
-        else:
-            return TypeError('unsupported type')
-        
-    def get(self, key):
-        '''Returns the value of an attribute of the internal element.
-
-        @param key Name of an attribute
-        @return String value of attribute
-        '''
-        return self._tree.get(key)
-
-    def getfield(self, key):
-        '''Returns a field with a name equal to a key.
-
-        @param key Name of a field
-        @return Template object
-        '''
-        return self._fielddict[key]
-    
-    def fromfile(self, path):
-        '''Creates an internal element from a file source.
-
-        @param path String value of path to source
-        '''
-        # Try ordinary parsing
-        try:
-            self.tree = _etree.parse(path).getroot()
-        except SyntaxError:
-            try:
-                # Try importing elementtidy
-                try:
-                    from elementtidy import TidyHTMLTreeBuilder as tidy
-                except ImportError:
-                    raise ImportError(_exceptions[5])
-                # Get element
-                source = _etree.tostring(tidy.parse(path).getroot())
-                self.tree = _etree.fromstring(source)
-            except SyntaxError:
-                raise TypeError('invalid source for Template class')
-            
-    def fromstring(self, instring):
-        '''Creates an internal element from a source string.
-
-        @param path String value of path to source
-        '''
-        # Try parsing the string as straight XML
-        try:
-            self.tree = _etree.fromstring(instring)
-        # Otherwise, try feeding it through elementtidy
-        except SyntaxError:
-            # Try importing elementtidy
-            try:
-                from elementtidy import TidyHTMLTreeBuilder as tidy
-            except ImportError:
-                raise ImportError(_exceptions[5])
-            # Feed parser
-            parser = tidy.TreeBuilder()
-            parser.feed(instring)
-            # Get element
-            self.tree = _etree.Element(_etree.tostring(parser.close()))                
-
-    def pipe(self, encoding='utf-8'):
-        '''Returns a string from the internal element's parent and resets the
-        object.
-
-        @param encoding Encoding type for return string (default: 'utf-8')
-        @return String from internal element
-        '''
-        # Output string
-        output = _etree.tostring(self._parent, encoding)
-        # Reset object
-        self.reset()
-        return output
-
-    def render(self, encoding='utf-8'):
-        '''Returns a string from the internal element's parent.
-
-        @param encoding Encoding type for return string (default: 'utf-8')
-        @return String from internal element
-        '''
-        return _etree.tostring(self._parent, encoding)
-
-    def reset(self):
-        '''Returns a Template object to its initial state'''
-        # Set fields back to original state
-        if self._type != 'root':
-            # Localize
-            siblings, fields = self._siblings, self._fields
-            parent, tree, children = self._parent, self._tree, self._children
-            # Remove added siblings
-            for item in siblings:
-                try:
-                    parent.remove(item)
-                except ValueError: pass
-            # Remove added fields
-            for item in (set(fields) - set(self._fielddict.values())):
-                fields.remove(item)
-            # Remove added children
-            for item in children:
-                try:
-                    tree.remove(item)
-                except ValueError: pass
-            # Clear tracking structures
-            self._siblings, self._children = list(), list()
-            # Remove text
-            del self.text
-            # Reset field if group Template
-            if self._type in _groups:
-                for item in fields:
-                    item.reset()
-        # Set root object back to orginal state
-        else:
-            # Clear parent and field lists
-            self._parent, self._fields = None, list()
-            # Clear internal mappings
-            self._fielddict.clear()
-            self._filter.clear()
-            # Recreate tree
-            self.tree = self._btree
-
-    def set(self, key, value):
-        '''Sets an attribute to a new value.
-
-        @param key Name of attribute
-        @param value Value attribute is set to
-        '''
-        self._tree.set(key, value)
-        # Make new _WebAttribute if set to auto
-        if self._auto:
-            # Check the name
-            name = _checkname(key)
-            # Create the web attribute
-            tattr = _WebAttribute(self._attrib, key, name)
-            # Assign new class as attribute of this object's superclass
-            setattr(self.__class__, name, tattr)
-
-    def setfield(self, key, node):
-        '''Sets a new field.
-
-        @param key Name of attribute
-        @param value Value to set attribute to
-        '''
-        # Add to internal trackers
-        self._fields.append(node)        
-        self._fielddict[key] = node
-        # Make field object attribute of self if auto on
-        if self._auto:
-            setattr(self, key, node)           
-
-    def substitute(self, dictionary):
-        '''Sets the internal element's text attribute from a string.Template.
-
-        @param dict Dictionary to feed through string.Template
-        '''
-        self.text = self._template.substitute(dictionary)
-
-    def unfilter(self, key):
-        '''Includes a field or group from a tree in a Template.
-
-        @param key Name of an field or group
-        '''
-        if isinstance(key, basestring):
-            # Remove from internal tracker
-            self._filter.remove(key)
-            # Re run tree build if not a group
-            if self._type not in _groups:
-                self.tree = self._btree
-                self.reset()
-            # Reset if group
-            else:
-                self.reset()
-        elif isinstance(key, (list, tuple)):
-            # Remove from internal tracker
-            for item in key:
-                self._filter.remove(item)
-            # Re run tree build if not a group
-            if self._type not in _groups:
-                self.tree = self._btree
-                self.reset()
-            # Reset if group
-            else:
-                self.reset()
-        else:
-            return TypeError('unsupported type')        
-
-    def write(self, path, encoding='utf-8'):
-        '''Writes a string of an internal element to a file.
-
-        @param path Path of destination file
-        @param encoding Encoding type for return string (default: 'utf-8')
-        '''
-        f = open(path, 'wb')
-        f.write(self.render(encoding))
-        f.close()
-            
-                   
-class Template(object):
-
-    '''Template engine for manipulating XML documents with sequence and
-    string operators.
-    ''' 
-    
-    def __new__(cls, src=None, parent=None, auto=True, omax=25, typ='root'):
-        '''Returns a new _Template derived class.
-
-        @param src Path, string, or element source (default: None)
-        @param parent Parent element of the source (default: None)
-        @param auto Turns automagic on and off (default: True)
-        @param omax Maximum number of times a field can repeat (default: 25)
-        @param typ Type of Template an object is (default: 'root')
-        '''
-        obj = type(_md5.new(str(_randint(0, _maxint))).digest(), (_Template,),
-            dict(_Template.__dict__))(src, parent, auto, omax, typ)
-        return obj 
-       
-
-class _WebAttribute(object):
-
-    '''Class for creating properties for manipulating the XML attributes of
-    an internal element.    
-    '''    
-
-    __slots__ = '_key', '_attrib', '_name'  
-
-    def __init__(self, attrib, key, name):
-        '''Initializes a _WebAttribute object.
-
-        @param attrib Dictionary of a Template's attributes
-        @param key Name of _WebAttribute's attribute
-        @param name Name of this _WebAttribute object
-        '''
-        self._key, self._attrib, self._name = key, attrib, name
-
-    def __repr__(self):
-        '''Returns string representation of object
-
-        @return String with name of attribute and value of attribute        
-        '''
-        return ''.join([self._key, ': ', self._attrib[self._key]])
-
-    def __get__(self, inst1, inst2):
-        '''Returns value of an attribute
-
-        @return String value of attribute        
-        '''
-        return self._attrib[self._key]
-
-    def __set__(self, inst, value):
-        '''Sets value of an attribute
-
-        @param inst Object the attribute belongs to
-        @param value Value to set the attribute to
-        '''
-        self._attrib[self._key] = value
-
-    def __delete__(self, inst):
-        '''Deletes an attribute.
-
-        @param inst Object the attribute belongs to
-        '''
-        # Delete the attribute
-        del self._attrib[self._key]
-        # Delete self as object of object's superclass
-        delattr(inst.__class__, self._name)
-        
-
-__all__ = ['Template']
-
-
-if __name__ == '__main__':
-    
-    import unittest
-
-    class TestWebString(unittest.TestCase):
-
-        '''Test class for webstring'''     
-
-        # Add tests        
-        groupend = '<table><tr class="tr1"><td id="td1" /><td id="td2" />' \
-            '</tr><tr class="tr2"><td id="td1" /><td id="td2" /></tr></table>'
-        altgroupend = '<table><tr class="tr2"><td id="td1" />' \
-            '<td id="td2" /></tr><tr class="tr1"><td id="td1" />' \
-            '<td id="td2" /></tr></table>'
-        subgroupend = '<tr class="tr1"><td id="td1" /><td id="td1" />' \
-            '<td id="td2" /></tr>'        
-        addtest = '<html><head><title id="title" /></head><body>' \
-            '<p id="content" /></body></html>'
-        altaddtest = '<html><body><p id="content" /></body><head>' \
-            '<title id="title" /></head></html>'        
-        child_add = '<body><p id="content" /><title id="title" /></body>'
-        child_group_add = '<head><title id="title" /><tr class="tr1">' \
-            '<td id="td1" /><td id="td2" /></tr></head>'
-        root_group_add = '<html><head><title id="title" /></head>' \
-            '<tr class="tr1"><td id="td1" /><td id="td2" /></tr></html>'
-        root_element_add = '<html><head><title id="title" /></head><p />' \
-            '</html>'
-        child_element_add = '<head><title id="title" /><p /></head>'
-        group_element_add = '<table><tr class="tr1"><td id="td1" />' \
-            '<td id="td2" /></tr><p /></table>'
-        subchild_element_add = '<tr class="tr1"><td id="td1" /><p />' \
-            '<td id="td2" /></tr>'
-        # Mul tests
-        multest = '<body><p id="content" /><p id="content" />' \
-            '<p id="content" /></body>'
-        root_mul = '<html><head><title id="title" /></head><body>' \
-            '<p id="content" /></body><head><title id="title" /></head>' \
-            '<body><p id="content" /></body><head><title id="title" />' \
-            '</head><body><p id="content" /></body></html>'
-        root_group_mul = '<table><tr class="tr1"><td id="td1" />' \
-            '<td id="td2" /></tr><tr class="tr1"><td id="td1" />' \
-            '<td id="td2" /></tr><tr class="tr1"><td id="td1" />' \
-            '<td id="td2" /></tr></table>'
-        subchild_group_mul = '<tr class="tr1"><td id="td1" />' \
-            '<td id="td1" /><td id="td1" /><td id="td2" /></tr>'
-        # Mod tests
-        modtest1 = '<html><head><title id="title">Test Page</title>' \
-            '</head><body /></html>'        
-        modtest2 = '<html><head><title id="title">Test Page</title></head>' \
-             '<body><p id="content">Content Goes Here</p></body></html>'
-        modtest3 = '<html><head><title id="title">Title</title></head>' \
-            '<body><p id="content">Test1</p><p id="content">Test2</p>' \
-            '<p id="content2">Test1</p><p id="content2">Test2</p>' \
-            '</body></html>'
-        modtest5 = '<head><title id="title">Test Page</title></head>'
-        groupmod = '<tr class="tr1"><td id="td1">Test Page</td>' \
-            '<td id="td2" /></tr>'
-        groupmod2 = '<table><tr class="tr1"><td id="td1">Test Page</td>' \
-            '<td id="td2">Content Goes Here</td></tr></table>'
-        groupmod3 = '<table><tr class="tr1"><td id="td1">Test1</td><td ' \
-            'id="td1">Test2</td><td id="td2">Test1</td><td id="td2">Test2' \
-            '</td></tr></table>'
-        # Pow tets
-        powtest1 = '<body><p id="content">Test1</p><p id="content">Test2' \
-            '</p></body>'
-        groupow = '<table><tr class="tr1"><td id="td1">1</td>' \
-            '<td id="td2">2</td></tr><tr class="tr1"><td id="td1">3' \
-            '</td><td id="td2">4</td></tr><tr class="tr1"><td id="td1">5' \
-            '</td><td id="td2">6</td></tr></table>'
-        # Templates
-        modtemplate1 = Template('<html><head><title id="title" /></head>' \
-            '<body /></html>')
-        modtemplate3 = Template('<html><head><title id="title"></title>' \
-            '</head><body><p id="content" /><p id="content2" /></body>' \
-            '</html>')        
-        gentemplate = Template(addtest)
-        atemplate = Template('<html><head><title id="title"></title></head>' \
-            '</html>')
-        btemplate = Template('<html><body><p id="content"></p></body></html>')
-        powtemplate = Template('<html><head /><body><p id="content" />' \
-            '</body></html>')
-        agrouptest = Template('<table><tr class="tr1"><td id="td1"/>' \
-            '<td id="td2"/></tr></table>')
-        bgrouptest = Template('<table><tr class="tr2"><td id="td1"/>' \
-            '<td id="td2"/></tr></table>')
-        # Data structures        
-        powdict = {'content1':'Test1', 'content2':'Test2'}
-        powtup = ('Test1', 'Test2')
-        moddict = {'content':'Content Goes Here', 'title':'Test Page'}
-        groupdict = {'td1':'Test Page', 'td2':'Content Goes Here'}
-        modtup = ('Test Page', 'Content Goes Here')
-        grouptup = [['1', '2'], ['3', '4'], ['5', '6']]
-        groupowdict = {'2':['1', '2'], '4':['3', '4'], '6':['5', '6']}
-
-        def test_root_add(self):
-            '''Tests adding of two root Template instances'''
-            self.assertEqual(self.addtest, self.atemplate + self.btemplate)
-
-        def test_root_radd(self):
-            '''Tests the right-side adding of two root Template instances'''
-            final = '<html><body><p id="content" /></body><head>' \
-                '<title id="title" /></head></html>'
-            self.assertEqual(final, self.btemplate + self.atemplate)
-
-        def test_root_iadd(self):
-            '''Tests the modifying adding of two root Template instances'''
-            self.atemplate += self.btemplate
-            self.assertEqual(self.addtest, self.atemplate.pipe())
-
-        def test_child_add(self):
-            '''Tests the adding of two field instances'''
-            final = '<head><title id="title" /><p id="content" /></head>'
-            self.assertEqual(final, self.atemplate.title +
-                self.btemplate.content)
-
-        def test_child_radd(self):
-            '''Tests the right-side adding of two field instances'''
-            self.assertEqual(self.child_add, self.btemplate.content +
-                self.atemplate.title)            
-
-        def test_child_iadd(self):
-            '''Tests the modifying adding of two field Templates'''
-            self.btemplate.content += self.atemplate.title
-            self.assertEqual(self.child_add, self.btemplate.content.pipe())
-
-        def test_group_child_add(self):
-            '''Tests the adding of two group field instances'''
-            self.assertEqual(self.groupend, self.agrouptest.tr1 +
-                self.bgrouptest.tr2)
-
-        def test_group_child_radd(self):
-            '''Tests the right-side adding of two group field
-            instances
-            '''            
-            self.assertEqual(self.altgroupend, self.bgrouptest.tr2 +
-                self.agrouptest.tr1)
-
-        def test_group_child_iadd(self):
-            '''Tests the modifying adding of two group field
-            instances'''
-            self.agrouptest.tr1 += self.bgrouptest.tr2
-            self.assertEqual(self.groupend, self.agrouptest.tr1.pipe())
-
-        def test_group_subchild_add(self):
-            '''Tests the adding of two group subchild Template instances'''
-            self.assertEqual(self.subgroupend, self.agrouptest.tr1.td1 +
-                self.bgrouptest.tr2.td1)
-
-        def test_group_subchild_radd(self):
-            '''Tests the right-side adding of two group subchild Template
-            instances
-            '''
-            final = '<tr class="tr2"><td id="td1" /><td id="td1" />' \
-                '<td id="td2" /></tr>'
-            self.assertEqual(final, self.bgrouptest.tr2.td1 +
-                self.agrouptest.tr1.td1)
-
-        def test_group_subchild_iadd(self):
-            '''Tests the modifying adding of two group subchild Template
-            instances
-            '''
-            self.agrouptest.tr1.td1 += self.bgrouptest.tr2.td1
-            self.assertEqual(self.subgroupend, self.agrouptest.tr1.td1.pipe())
-
-        def test_child_root_iadd(self):
-            '''Tests the modifying adding of one child and one root Template
-            object
-            '''
-            final = '<head><title id="title" /><body><p id="content" />' \
-            '</body></head>'
-            self.atemplate.title += self.btemplate
-            self.assertEqual(final, self.atemplate.title.pipe())
-
-        def test_child_child_group_iadd(self):
-            '''Tests the modifying adding of one child and one child group
-            Template object
-            '''
-            self.atemplate.title += self.agrouptest.tr1
-            self.assertEqual(self.child_group_add,
-                self.atemplate.title.pipe())
-
-        def test_child_subchild_group_iadd(self):
-            '''Tests the modifying adding of one child and one subchild group
-            Template object
-            '''
-            final = '<head><title id="title" /><td id="td1" /></head>'
-            self.atemplate.title += self.agrouptest.tr1.td1
-            self.assertEqual(final, self.atemplate.title.pipe())                
-
-        def test_root_child_iadd(self):
-            '''Tests the modifying adding of one root and one field
-            object
-            '''
-            final = '<html><body><p id="content" /></body>' \
-            '<title id="title" /></html>'
-            self.btemplate += self.atemplate.title
-            self.assertEqual(final, self.btemplate.pipe())
-
-        def test_root_child_group_iadd(self):
-            '''Tests the modifying adding of one child group and one root
-            Template object
-            '''
-            self.atemplate += self.agrouptest.tr1
-            self.assertEqual(self.root_group_add, self.atemplate.pipe())
-
-        def test_root_subchild_group_iadd(self):
-            '''Tests the modifying adding of one child group and one root
-            Template object
-            '''
-            final = '<html><head><title id="title" /></head><td id="td1" />' \
-                '<td id="td2" /></html>'
-            self.atemplate += self.agrouptest.tr1.td1
-            self.assertEqual(final, self.atemplate.pipe())
-
-        def test_child_group_subchild_group_iadd(self):
-            '''Tests the modifying adding of one child group and one subchild
-            group Template object
-            '''
-            final = '<table><tr class="tr1"><td id="td1" /><td id="td2" />' \
-                '</tr><td id="td1" /></table>'
-            self.agrouptest.tr1 += self.bgrouptest.tr2.td1
-            self.assertEqual(final, self.agrouptest.tr1.pipe())
-
-        def test_subchild_group_child_group_iadd(self):
-            '''Tests the modifying adding of one child group and one subchild
-            group Template object
-            '''
-            final = '<tr class="tr2"><td id="td1" /><tr class="tr1">' \
-                '<td id="td1" /><td id="td2" /></tr><td id="td2" /></tr>'
-            self.bgrouptest.tr2.td1 += self.agrouptest.tr1
-            self.assertEqual(final, self.bgrouptest.tr2.td1.pipe())            
-
-        def test_root_element_radd(self):
-            '''Tests the right-side adding of one root Template object
-            and one Element object'''
-            self.assertEqual(self.root_element_add, _etree.Element('p') +
-                self.atemplate)
-
-        def test_root_element_iadd(self):
-            '''Tests the modifying adding of one root Template object and one
-            Element object
-            '''
-            self.atemplate += _etree.Element('p')
-            self.assertEqual(self.root_element_add, self.atemplate.pipe())
-
-        def test_child_element_radd(self):
-            '''Tests the right-side adding of one field object and
-            one Element object
-            '''
-            self.assertEqual(self.child_element_add, _etree.Element('p') +
-                self.atemplate.title)
-
-        def test_child_element_iadd(self):
-            '''Tests the modifying adding of one field object and one
-            Element object
-            '''
-            self.atemplate.title += _etree.Element('p')
-            self.assertEqual(self.child_element_add,
-                self.atemplate.title.pipe())
-
-        def test_child_group_element_radd(self):
-            '''Tests the right-side adding of one child group Template object
-            and one Element object.
-            '''
-            self.assertEqual(self.group_element_add, _etree.Element('p') +
-                self.agrouptest.tr1)
-
-        def test_child_group_element_iadd(self):
-            '''Tests the modifying adding of one child group Template object
-            and one Element object
-            '''
-            self.agrouptest.tr1 += _etree.Element('p')
-            self.assertEqual(self.group_element_add,
-                self.agrouptest.tr1.pipe())
-
-        def test_subchild_group_element_radd(self):
-            '''Tests the right-side adding of one subchild group Template
-            object and one Element object.
-            '''
-            self.assertEqual(self.subchild_element_add, _etree.Element('p') +
-                self.agrouptest.tr1.td1)
-
-        def test_subchild_group_element_iadd(self):
-            '''Tests the modifying adding of one subchild group Template
-            object and one Element object
-            '''
-            self.agrouptest.tr1.td1 += _etree.Element('p')
-            self.assertEqual(self.subchild_element_add,
-                self.agrouptest.tr1.td1.pipe())             
-
-        def test_root_radd_raise(self):
-            '''Test raises TypeError if the wrong type is right-side added
-            with a root Template object
-            '''
-            def tempfunc():
-                return [1, 1, 1] + self.atemplate
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_root_iadd_raise(self):
-            '''Test raises TypeError if the wrong type is modifyingly added
-            with a root Template object
-            '''
-            def tempfunc():
-                a = self.atemplate.copy()
-                a += [1, 1, 1]
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_child_radd_raise(self):
-            '''Test raises TypeError if the wrong type is right-side added
-            with a field object
-            '''
-            def tempfunc():
-                return [1, 1, 1] + self.atemplate.title
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_child_iadd_raise(self):
-            '''Test raises TypeError if the wrong type is modifyingly added
-            with a field object
-            '''
-            def tempfunc():
-                a = self.atemplate.copy()
-                a.title += [1,1,1]
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_child_group_radd_raise(self):
-            '''Test raises TypeError if the wrong type is right-side added
-            with a root group Template object'''
-            def tempfunc():
-                return [1,1,1] + self.agrouptest.tr1 
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_child_group_iadd_raise(self):
-            '''Test raises TypeError if the wrong type is modifyingly
-            added with a child group Template object'''
-            def tempfunc():
-                a = self.agrouptest.copy()
-                a.tr1 += [1, 1, 1]
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_subchild_group_radd_raise(self):
-            '''Test raises TypeError if the wrong type is right-side added
-            with a subchild group Template object'''
-            def tempfunc():
-                return [1, 1, 1] + self.agrouptest.tr1.td1
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_subchild_group_iadd_raise(self):
-            '''Test raises TypeError if the wrong type is modifyingly added
-            with a subchild group Template object'''
-            def tempfunc():
-                a = self.agrouptest.copy()
-                a.tr1.td1 += [1, 1, 1]
-            self.assertRaises(TypeError, tempfunc)             
-
-        def test_child_mul(self):
-            '''Tests the repetition of a field'''
-            self.assertEqual(self.multest, self.gentemplate.content * 3)
-
-        def test_child_rmul(self):
-            '''Tests repetition of a field with the number on the
-            right side
-            '''
-            self.assertEqual(self.multest, 3 * self.gentemplate.content)
-
-        def test_child_imul(self):
-            '''Tests modifying repetition of a field'''
-            self.gentemplate.content *= 3
-            self.assertEqual(self.multest, self.gentemplate.content.pipe())
-
-        def test_root_rmul(self):
-            '''Tests repetition of a root Template with the number on the
-            right side'''
-            self.assertEqual(self.root_mul, 3 * self.gentemplate)
-
-        def test_root_imul(self):
-            '''Tests modifying repetition of a root Template'''
-            self.gentemplate *= 3            
-            self.assertEqual(self.root_mul, self.gentemplate.pipe())
-
-        def test_child_group_rmul(self):
-            '''Tests repetition of a child group Template with the number on
-            the right side
-            '''
-            self.assertEqual(self.root_group_mul, 3 * self.agrouptest.tr1)
-
-        def test_child_group_imul(self):
-            '''Tests modifying repetition of a child root Template'''
-            self.agrouptest.tr1 *= 3            
-            self.assertEqual(self.root_group_mul, self.agrouptest.tr1.pipe())
-
-        def test_subchild_group_mul(self):
-            '''Tests the repetition of a subchild group Template'''
-            self.assertEqual(self.subchild_group_mul, self.agrouptest.tr1.td1
-                * 3)
-
-        def test_subchild_group_rmul(self):
-            '''Tests repetition of a subchild group Template with the number
-            on the right side
-            '''
-            self.assertEqual(self.subchild_group_mul, 3 *
-                self.agrouptest.tr1.td1)
-
-        def test_subchild_group_imul(self):
-            '''Tests modifying repetition of a subchild group Template'''
-            self.agrouptest.tr1.td1 *= 3            
-            self.assertEqual(self.subchild_group_mul,
-                self.agrouptest.tr1.td1.pipe())
-
-        def test_child_imul_rep(self):
-            '''Tests restraint on max modifying repetition of a child
-            Template
-            '''
-            def tempfunc():
-                a = self.gentemplate.copy()
-                a.content.max = 2
-                a.content *= 3
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_root_imul_rep(self):
-            '''Tests restraint on max modifying repetition of a root
-            Template
-            '''
-            def tempfunc():
-                a = self.gentemplate.copy()
-                a.max = 2
-                a *= 3
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_child_group_imul_rep(self):
-            '''Tests restraint on max modifying repetition of a child
-            group Template
-            '''
-            def tempfunc():
-                a = self.agrouptest.copy()
-                a.tr1.max = 2
-                a.tr1 *= 3
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_subchild_group_imul_rep(self):
-            '''Tests restraint on max modifying repetition of a subchild
-            group Template
-            '''
-            def tempfunc():
-                a = self.agrouptest.copy()
-                a.tr1.td1.max = 2
-                a.tr1.td1 *= 3
-            self.assertRaises(TypeError, tempfunc)
-        
-        def test_root_string_mod(self):
-            '''Tests string interpolation of a root Template'''
-            self.assertEqual(self.modtest1, self.modtemplate1 % 'Test Page')
-            
-        def test_root_string_imod(self):
-            '''Tests a modifying string interpolation of a root Template'''
-            self.modtemplate1 %= 'Test Page'
-            self.assertEqual(self.modtest1, self.modtemplate1.pipe())
-
-        def test_child_string_imod(self):
-            '''Tests a modifying string interpolation of a field'''
-            self.modtemplate1.title %= 'Test Page'
-            self.assertEqual(self.modtest5, self.modtemplate1.title.pipe())
-
-        def test_subchild_string_imod(self):
-            '''Tests a modifying string interpolation of a subchild group
-            Template
-            '''
-            self.agrouptest.tr1.td1 %= 'Test Page'
-            self.assertEqual(self.groupmod, self.agrouptest.tr1.td1.pipe())
-
-        def test_root_string_mod_toofew(self):
-            '''Tests if TypeError raised if too few inputs are passed to a
-            root Template
-            '''
-            def tempfunc():
-                return self.gentemplate % 'Test Page'
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_root_with_group_string_mod_toofew(self):
-            '''Tests if TypeError raised if too few inputs are passed to a
-            root containing a group Template
-            '''
-            def tempfunc():
-                return self.agrouptest % 'Test Page'
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_child_group_string_mod_toofew(self):
-            '''Tests if TypeError raised if too few inputs are passed to a
-            child group Template
-            '''
-            def tempfunc():
-                return self.agrouptest.tr1 % 'Test Page'
-            self.assertRaises(TypeError, tempfunc) 
-
-        def test_list_imod(self):
-            '''Tests a modifying list interpolation of a Template'''
-            self.gentemplate %= list(self.modtup)
-            self.assertEqual(self.modtest2, self.gentemplate.pipe())
-
-        def test_list_group_imod(self):
-            '''Tests a modifying list interpolation of a group Template'''
-            self.agrouptest.tr1 %= list(self.modtup)
-            self.assertEqual(self.groupmod2, self.agrouptest.pipe())        
-
-        def test_list_list_imod_expand(self):
-            '''Tests a modifying list list interpolation/expansion of a
-            Template
-            '''
-            self.modtemplate3 %= ['Title', ['Test1', 'Test2'],
-                ['Test1', 'Test2']]
-            self.assertEqual(self.modtest3, self.modtemplate3.pipe())
-
-        def test_list_list_group_imod_expand(self):
-            '''Tests a modifying list list interpolation/expansion of a
-            group Template
-            '''
-            self.agrouptest.tr1 %= [['Test1', 'Test2'], ['Test1', 'Test2']]
-            self.assertEqual(self.groupmod3, self.agrouptest.pipe())            
-
-        def test_list_tuple_imod_expand(self):
-            '''Tests a modifying list tuple interpolation/expansion of a
-            Template
-            '''
-            self.modtemplate3 %= ['Title', ('Test1', 'Test2'),
-                ('Test1', 'Test2')]
-            self.assertEqual(self.modtest3, self.modtemplate3.pipe())
-
-        def test_list_tuple_group_imod_expand(self):
-            '''Tests a modifying list tuple interpolation/expansion of a
-            group Template
-            '''
-            self.agrouptest.tr1 %= [('Test1', 'Test2'), ('Test1', 'Test2')]
-            self.assertEqual(self.groupmod3, self.agrouptest.pipe())
-
-        def test_list_dict_imod_expand(self):
-            '''Tests a modifying list dictionary interpolation/expansion of a
-            Template
-            '''
-            self.modtemplate3 %= ['Title', {'a':'Test1', 'b':'Test2'},
-                {'d':'Test2', 'c':'Test1'}]
-            self.assertEqual(self.modtest3, self.modtemplate3.pipe())
-
-        def test_list_dict_group_imod_expand(self):
-            '''Tests a modifying list dict interpolation/expansion of a
-            group Template
-            '''
-            self.agrouptest.tr1 %= [{'a':'Test1', 'b':'Test2'},
-                {'d':'Test2', 'c':'Test1'}]
-            self.assertEqual(self.groupmod3, self.agrouptest.pipe())            
-
-        def test_list_mod_wrongtype(self):
-            '''Tests if a TypeError is raised if unsupported types in a list
-            are interpolated
-            '''
-            def tempfunc():
-                return self.gentemplate % [set(['Test Page'])]                
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_list_group_mod_wrongtype(self):
-            '''Tests if a TypeError is raised if unsupported types in a list
-            are interpolated into a group template
-            '''
-            def tempfunc():
-                return self.agrouptest.tr1 % [set(['Test Page'])]
-            self.assertRaises(TypeError, tempfunc)            
-
-        def test_list_mod_toomany(self):
-            '''Tests if a TypeError is raised if too many items in a list are
-            interpolated
-            '''
-            def tempfunc():
-                return self.gentemplate % ['Test Page', 'Content Goes Here',
-                    'Too Many']
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_list_group_mod_toomany(self):
-            '''Tests if a TypeError is raised if too many items in a list are
-            interpolated into a group template
-            '''
-            def tempfunc():
-                return self.agrouptest.tr1 % ['Test Page',
-                    'Content Goes Here', 'Too Many']
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_list_mod_toofew(self):
-            '''Tests if a TypeError is raised if too few items in a list are
-            interpolated
-            '''
-            def tempfunc():
-                return self.gentemplate % ['Test Page']
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_list_group_mod_toofew(self):
-            '''Tests if a TypeError is raised if too few items in a list are
-            interpolated into a group template
-            '''
-            def tempfunc():
-                return self.agrouptest.tr1 % ['Test Page']
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_tuple_imod(self):
-            '''Tests a modifying tuple interpolation of a Template'''
-            self.gentemplate %= self.modtup
-            self.assertEqual(self.modtest2, self.gentemplate.pipe())
-
-        def test_tuple_group_imod(self):
-            '''Tests a modifying tuple interpolation of a group Template'''
-            self.agrouptest.tr1 %= self.modtup
-            self.assertEqual(self.groupmod2, self.agrouptest.pipe())            
-
-        def test_tuple_list_imod_expand(self):
-            '''Tests a modifying tuple list interpolation/expansion of a
-            Template
-            '''
-            self.modtemplate3 %= ('Title', ['Test1', 'Test2'],
-                ['Test1', 'Test2'])
-            self.assertEqual(self.modtest3, self.modtemplate3.pipe())
-
-        def test_tuple_list_group_imod_expand(self):
-            '''Tests a modifying tuple list interpolation/expansion of a
-            group Template
-            '''
-            self.agrouptest.tr1 %= (['Test1', 'Test2'], ['Test1', 'Test2'])
-            self.assertEqual(self.groupmod3, self.agrouptest.pipe())            
-
-        def test_tuple_tuple_imod_expand(self):
-            '''Tests a modifying tuple tuple interpolation/expansion of a
-            Template
-            '''
-            self.modtemplate3 %= ('Title', ('Test1', 'Test2'),
-                ('Test1', 'Test2'))
-            self.assertEqual(self.modtest3, self.modtemplate3.pipe())
-
-        def test_tuple_tuple_group_imod_expand(self):
-            '''Tests a modifying tuple tuple interpolation/expansion of a
-            group Template
-            '''
-            self.agrouptest.tr1 %= (('Test1', 'Test2'), ('Test1', 'Test2'))
-            self.assertEqual(self.groupmod3, self.agrouptest.pipe())
-
-        def test_tuple_dict_imod_expand(self):
-            '''Tests a modifying tuple dictionary interpolation/expansion of a
-            Template
-            '''
-            self.modtemplate3 %= ('Title', {'a':'Test1', 'b':'Test2'},
-                {'d':'Test2', 'c':'Test1'})
-            self.assertEqual(self.modtest3, self.modtemplate3.pipe())
-
-        def test_tuple_dict_group_imod_expand(self):
-            '''Tests a modifying tuple dict interpolation/expansion of a
-            group Template
-            '''
-            self.agrouptest.tr1 %= ({'a':'Test1', 'b':'Test2'},
-                {'d':'Test2', 'c':'Test1'})
-            self.assertEqual(self.groupmod3, self.agrouptest.pipe())
-
-        def test_tuple_mod_wrongtype(self):
-            '''Tests if a TypeError is raised if unsupported types in a tuple
-            are interpolated
-            '''
-            def tempfunc():
-                return self.gentemplate % (set(['Test Page']), )
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_tuple_group_mod_wrongtype(self):
-            '''Tests if a TypeError is raised if unsupported types in a tuple
-            are interpolated into a group template
-            '''
-            def tempfunc():
-                return self.agrouptest.tr1 % (set(['Test Page']), )
-            self.assertRaises(TypeError, tempfunc)            
-
-        def test_tuple_mod_toomany(self):
-            '''Tests if a TypeError is raised if too many items in a tuple are
-            interpolated
-            '''
-            def tempfunc():
-                return self.gentemplate % ('Test Page', 'Content Goes Here',
-                    'Too Many')
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_tuple_group_mod_toomany(self):
-            '''Tests if a TypeError is raised if too many items in a tuple are
-            interpolated into a group template
-            '''
-            def tempfunc():
-                return self.agrouptest.tr1 % ('Test Page',
-                    'Content Goes Here', 'Too Many')
-            self.assertRaises(TypeError, tempfunc)              
-
-        def test_tuple_mod_toofew(self):
-            '''Tests if a TypeError is raised if too few items in a tuple are
-            interpolated
-            '''
-            def tempfunc():
-                return self.gentemplate % ('Test Page')
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_dict_imod(self):
-            '''Tests a modifying dictionary interpolation of a Template'''
-            self.gentemplate %= self.moddict
-            self.assertEqual(self.modtest2, self.gentemplate.pipe())
-
-        def test_dict_group_imod(self):
-            '''Tests a modifying dict interpolation of a group Template'''
-            self.agrouptest.tr1 %= self.groupdict
-            self.assertEqual(self.groupmod2, self.agrouptest.pipe())
-
-        def test_dict_list_imod_expand(self):
-            '''Tests a modifying dictionary list interpolation/expansion of a
-            Template
-            '''
-            self.modtemplate3 %= {'title':'Title',
-                'content':['Test1', 'Test2'], "content2":['Test1', 'Test2']}
-            self.assertEqual(self.modtest3, self.modtemplate3.pipe())
-
-        def test_dict_list_group_imod_expand(self):
-            '''Tests a modifying dict list interpolation/expansion of a
-            group Template
-            '''
-            self.agrouptest.tr1 %= {'td1':['Test1', 'Test2'],
-                'td2':['Test1', 'Test2']}
-            self.assertEqual(self.groupmod3, self.agrouptest.pipe())            
-
-        def test_dict_tuple_imod_expand(self):
-            '''Tests a modifying dictionary tuple interpolation/expansion of a
-            Template
-            '''
-            self.modtemplate3 %= {'title':'Title', 'content':('Test1', 'Test2'),
-                "content2":('Test1', 'Test2')}
-            self.assertEqual(self.modtest3, self.modtemplate3.pipe())
-
-        def test_dict_tuple_group_imod_expand(self):
-            '''Tests a modifying dict tuple interpolation/expansion of a
-            group Template
-            '''
-            self.agrouptest.tr1 %= {'td1':('Test1', 'Test2'),
-                'td2':('Test1', 'Test2')}
-            self.assertEqual(self.groupmod3, self.agrouptest.pipe())            
-
-        def test_dict_dict_imod_expand(self):
-            '''Tests a modifying dictionary dictionary interpolation/expansion
-            of a Template
-            '''
-            self.modtemplate3 %= {'title':'Title', 'content':{'a':'Test1',
-                'b':'Test2'}, 'content2':{'d':'Test2', 'c':'Test1'}}
-            self.assertEqual(self.modtest3, self.modtemplate3.pipe())
-
-        def test_dict_dict_group_imod_expand(self):
-            '''Tests a modifying dict dict interpolation/expansion of a group
-            Template
-            '''
-            self.agrouptest.tr1 %= {'td1':{'a':'Test1', 'b':'Test2'},
-                'td2':{'a':'Test1', 'b':'Test2'}}
-            self.assertEqual(self.groupmod3, self.agrouptest.pipe())
-
-        def test_dict_mod_wrongtype(self):
-            '''Tests if a TypeError is raised if unsupported types in a
-            dictionary are interpolated
-            '''
-            def tempfunc():
-                return self.gentemplate % {'content':set(['Test Page'])}
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_dict_group_mod_wrongtype(self):
-            '''Tests if a TypeError is raised if unsupported types in a
-            dictionary are interpolated into a group Template
-            '''
-            def tempfunc():
-                return self.agrouptest.tr1 % {'td1':set(['Test Page'])}
-            self.assertRaises(TypeError, tempfunc)            
-
-        def test_dict_mod_toomany(self):
-            '''Tests if a TypeError is raised if too many items in a dictionary
-            are interpolated
-            '''
-            def tempfunc():
-                return self.gentemplate % {'content':'Content Goes Here',
-                    'title':'Test Page', 'test':'Too many'}
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_dict_group_mod_toomany(self):
-            '''Tests if a TypeError is raised if too many items in a dictionary
-            are interpolated into a group Template
-            '''
-            def tempfunc():
-                return self.agrouptest.tr1 % {'td1':'Content Goes Here',
-                    'td2':'Test Page', 'td3':'Too many'}
-            self.assertRaises(TypeError, tempfunc)            
-
-        def test_dict_mod_toofew(self):
-            '''Tests if a TypeError is raised if too few items in a dictionary
-            are interpolated
-            '''
-            def tempfunc():
-                return self.gentemplate % {'content':'Content Goes Here'}
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_dict_group_mod_toofew(self):
-            '''Tests if a TypeError is raised if too few items in a dictionary
-            are interpolated into a group Template
-            '''
-            def tempfunc():
-                return self.gentemplate % {'content':'Content Goes Here'}
-            self.assertRaises(TypeError, tempfunc)            
-
-        def test_list_pow(self):
-            '''Tests expansion of a field Template by a list'''
-            self.assertEqual(self.powtest1, self.powtemplate.content **
-                list(self.powtup))
-
-        def test_list_ipow(self):
-            '''Tests a modifying expansion of a field Template by a list'''
-            self.powtemplate.content **= list(self.powtup)
-            self.assertEqual(self.powtest1, self.powtemplate.content.pipe())
-
-        def test_list_group_ipow(self):
-            '''Tests a modifying expansion of a group Template by a list'''
-            self.agrouptest.tr1 **= list(self.grouptup)
-            self.assertEqual(self.groupow, self.agrouptest.tr1.pipe())
-
-        def test_list_pow_rep(self):
-            '''Raises an TypeError if list expansion exceeds max repetitions'''
-            def tempfunc():
-                a = self.powtemplate.copy()
-                a.content.max = 1
-                return a.content ** list(self.powtup)
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_list_group_pow_rep(self):
-            '''Raises an TypeError if list expansion exceeds max repetitions
-            in a group Template
-            '''
-            def tempfunc():
-                a = self.agrouptest.copy()
-                a.tr1.max = 1
-                return a.tr1 ** list(self.grouptup)
-            self.assertRaises(TypeError, tempfunc)            
-
-        def test_tuple_ipow(self):
-            '''Tests a modifying expansion of a field object by a
-            tuple
-            '''
-            self.powtemplate.content **= self.powtup
-            self.assertEqual(self.powtest1, self.powtemplate.content.pipe())
-
-        def test_tuple_group_ipow(self):
-            '''Tests a modifying expansion of a group Template by a tuple'''
-            self.agrouptest.tr1 **= self.grouptup
-            self.assertEqual(self.groupow, self.agrouptest.tr1.pipe())
-
-        def test_tuple_pow_rep(self):
-            '''Raises an TypeError if tuple expansion exceeds max repetitions'''
-            def tempfunc():
-                a = self.powtemplate.copy()
-                a.content.max = 1
-                a.content ** self.powtup
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_tuple_group_pow_rep(self):
-            '''Raises an TypeError if tuple expansion exceeds max repetitions
-            in a group Template
-            '''
-            def tempfunc():
-                a = self.agrouptest.copy()
-                a.tr1.max = 1
-                return a.tr1 ** self.grouptup
-            self.assertRaises(TypeError, tempfunc)   
-
-        def test_dict_ipow(self):
-            '''Tests a modifying expansion of a field object by a
-            dictionary
-            '''
-            self.powtemplate.content **= self.powdict.copy()
-            self.assertEqual(self.powtest1, self.powtemplate.content.pipe())
-
-        def test_dict_group_ipow(self):
-            '''Tests a modifying expansion of a group Template by a dict'''
-            self.agrouptest.tr1 **= self.groupowdict
-            self.assertEqual(self.groupow, self.agrouptest.tr1.pipe())
-
-        def test_dict_pow_rep(self):
-            '''Raises an TypeError if dictionary expansion exceeds max
-            repetitions
-            '''
-            def tempfunc():
-                a = self.powtemplate.copy()
-                a.content.max = 1
-                a.content ** self.powdict.copy()
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_dict_group_pow_rep(self):
-            '''Raises an TypeError if dict expansion exceeds max repetitions
-            in a group Template
-            '''
-            def tempfunc():
-                a = self.agrouptest.copy()
-                a.tr1.max = 1
-                return a.tr1 ** self.groupowdict
-            self.assertRaises(TypeError, tempfunc)               
-
-        def test_pow_wrongtype(self):
-            '''Raises an TypeError if wrong type passed in for expansion'''
-            def tempfunc():
-                return self.powtemplate ** 'This is a test.'
-            self.assertRaises(TypeError, tempfunc)
-
-        def test_group_pow_wrongtype(self):
-            '''Raises an TypeError if wrong type passed in for expansion'''
-            def tempfunc():
-                return self.agrouptest.tr1 ** 'This is a test.'
-            self.assertRaises(TypeError, tempfunc)            
-
-        def test_delattr_dict_field(self):
-            '''Tests deletion of field attributes from internal dictionary'''
-            a = self.btemplate.copy()
-            del a.content
-            self.assertEqual(False, a._fielddict.has_key('content'))
-
-        def test_delattr_dict_group(self):
-            '''Tests deletion of group attributes from internal dictionary'''
-            a = self.agrouptest.copy()
-            del a.tr1
-            self.assertEqual(False, a._fielddict.has_key('tr1'))  
-
-        def test_delattr_dict_subchild(self):
-            '''Tests deletion of group attributes from internal dictionary'''
-            a = self.agrouptest.copy()
-            del a.tr1.td1
-            self.assertEqual(False, a.tr1._fielddict.has_key('td1'))            
-
-        def test_delattr_field(self):
-            '''Tests deletion of field attributes from internal list'''
-            a = self.btemplate.copy()
-            del a.content
-            x = False
-            for i in a.tree.getiterator():
-                if i.get('id') == 'content':
-                    x == True
-            self.assertEqual(False, x)
-
-        def test_delattr_group(self):
-            '''Tests deletion of group attributes from internal list'''
-            a = self.agrouptest.copy()
-            del a.tr1
-            x = False
-            for i in a.tree.getiterator():
-                if i.get('class') == 'tr1':
-                    x == True
-            self.assertEqual(False, x)
-
-        def test_delattr_subchild(self):
-            '''Tests deletion of subchild attributes from internal list'''
-            a = self.agrouptest.copy()
-            del a.tr1.td1
-            x = False
-            for i in a.tr1.tree.getiterator():
-                if i.get('class') == 'td1':
-                    x == True
-            self.assertEqual(False, x)            
-
-        def test_delattr_attribute(self):
-            '''Tests deletion of attribute attributes'''
-            a = self.btemplate.copy()
-            del a.content.id
-            self.assertEqual(False, hasattr(a.content, 'id'))
-
-        def test_delattr_subchild_attribute(self):
-            '''Tests deletion of subchild attribute attributes'''
-            a = self.agrouptest.copy()
-            del a.tr1.td1.id
-            self.assertEqual(False, hasattr(a.tr1.td1, 'id'))             
-
-        def test_getitem(self):
-            '''Tests getting Template contents by index'''
-            a = self.btemplate.copy()
-            a.content %= 'Test'
-            self.assertEqual('Test', a[0].text)
-
-        def test_group_getitem(self):
-            '''Tests getting group Template contents by index'''
-            a = self.agrouptest.copy()
-            self.assertEqual(True, hasattr(a[0], 'td1'))              
-
-        def test_subchild_getitem(self):
-            '''Tests getting subchild Template contents by index'''
-            a = self.agrouptest.copy()
-            a.tr1.td1 %= 'Test'
-            self.assertEqual('Test', a[0][0].text)                          
-
-        def test_setitem(self):
-            '''Tests setting Template contents by index'''
-            a = self.btemplate.copy()
-            a[0] %= 'Test'
-            self.assertEqual('Test', a[0].text)
-
-        def test_group_setitem(self):
-            '''Tests setting group Template contents by index'''
-            a = self.agrouptest.copy()
-            a[0].id = 'Test'
-            self.assertEqual('Test', a[0].id)            
-
-        def test_subchild_setitem(self):
-            '''Tests setting subchild Template contents by index'''
-            a = self.agrouptest.copy()
-            a[0][0] %= 'Test'
-            self.assertEqual('Test', a[0][0].text)