diff --git a/tablib/packages/markup.py b/tablib/packages/markup.py
index 1973c00..234f116 100644
--- a/tablib/packages/markup.py
+++ b/tablib/packages/markup.py
@@ -68,7 +68,7 @@ class element:
"""Append the actual tags to content."""
out = "<%s" % tag
- for key, value in kwargs.items( ):
+ for key, value in kwargs.iteritems( ):
if value is not None: # when value is None that means stuff like <... checked>
key = key.strip('_') # strip this so class_ will mean class, etc.
if key == 'http_equiv': # special cases, maybe change _ to - overall?
@@ -156,17 +156,17 @@ class page:
if mode == 'strict_html' or mode == 'html':
self.onetags = valid_onetags
- self.onetags += list(map( str.lower, self.onetags ))
+ self.onetags += map( string.lower, self.onetags )
self.twotags = valid_twotags
- self.twotags += list(map( str.lower, self.twotags ))
+ self.twotags += map( string.lower, self.twotags )
self.deptags = deprecated_onetags + deprecated_twotags
- self.deptags += list(map( str.lower, self.deptags ))
+ self.deptags += map( string.lower, self.deptags )
self.mode = 'strict_html'
elif mode == 'loose_html':
self.onetags = valid_onetags + deprecated_onetags
- self.onetags += list(map( str.lower, self.onetags ))
+ self.onetags += map( string.lower, self.onetags )
self.twotags = valid_twotags + deprecated_twotags
- self.twotags += list(map( str.lower, self.twotags ))
+ self.twotags += map( string.lower, self.twotags )
self.mode = mode
elif mode == 'xml':
if onetags and twotags:
@@ -183,7 +183,7 @@ class page:
def __getattr__( self, attr ):
if attr.startswith("__") and attr.endswith("__"):
- raise AttributeError(attr)
+ raise AttributeError, attr
return element( attr, case=self.case, parent=self )
def __str__( self ):
@@ -307,7 +307,7 @@ class page:
"""This convenience function is only useful for html.
It adds css stylesheet(s) to the document via the element."""
- if isinstance( filelist, str ):
+ if isinstance( filelist, basestring ):
self.link( href=filelist, rel='stylesheet', type='text/css', media='all' )
else:
for file in filelist:
@@ -319,20 +319,20 @@ class page:
a dictionary of the form { 'name':'content' }."""
if isinstance( mydict, dict ):
- for name, content in mydict.items( ):
+ for name, content in mydict.iteritems( ):
self.meta( name=name, content=content )
else:
- raise TypeError("Metainfo should be called with a dictionary argument of name:content pairs.")
+ raise TypeError, "Metainfo should be called with a dictionary argument of name:content pairs."
def scripts( self, mydict ):
"""Only useful in html, mydict is dictionary of src:type pairs will
be rendered as """
if isinstance( mydict, dict ):
- for src, type in mydict.items( ):
+ for src, type in mydict.iteritems( ):
self.script( '', src=src, type='text/%s' % type )
else:
- raise TypeError("Script should be given a dictionary of src:type pairs.")
+ raise TypeError, "Script should be given a dictionary of src:type pairs."
class _oneliner:
@@ -345,7 +345,7 @@ class _oneliner:
def __getattr__( self, attr ):
if attr.startswith("__") and attr.endswith("__"):
- raise AttributeError(attr)
+ raise AttributeError, attr
return element( attr, case=self.case, parent=None )
oneliner = _oneliner( case='lower' )
@@ -359,14 +359,14 @@ def _argsdicts( args, mydict ):
elif len( args ) == 1:
args = _totuple( args[0] )
else:
- raise Exception("We should have never gotten here.")
+ raise Exception, "We should have never gotten here."
- mykeys = list(mydict.keys( ))
- myvalues = list(map( _totuple, list(mydict.values( )) ))
+ mykeys = mydict.keys( )
+ myvalues = map( _totuple, mydict.values( ) )
- maxlength = max( list(map( len, [ args ] + myvalues )) )
+ maxlength = max( map( len, [ args ] + myvalues ) )
- for i in range( maxlength ):
+ for i in xrange( maxlength ):
thisdict = { }
for key, value in zip( mykeys, myvalues ):
try:
@@ -383,7 +383,7 @@ def _argsdicts( args, mydict ):
def _totuple( x ):
"""Utility stuff to convert string, int, float, None or anything to a usable tuple."""
- if isinstance( x, str ):
+ if isinstance( x, basestring ):
out = x,
elif isinstance( x, ( int, float ) ):
out = str( x ),
@@ -397,7 +397,7 @@ def _totuple( x ):
def escape( text, newline=False ):
"""Escape special html characters."""
- if isinstance( text, str ):
+ if isinstance( text, basestring ):
if '&' in text:
text = text.replace( '&', '&' )
if '>' in text:
@@ -419,7 +419,7 @@ _escape = escape
def unescape( text ):
"""Inverse of escape."""
- if isinstance( text, str ):
+ if isinstance( text, basestring ):
if '&' in text:
text = text.replace( '&', '&' )
if '>' in text:
@@ -481,4 +481,4 @@ class CustomizationError( MarkupError ):
self.message = "If you customize the allowed elements, you must define both types 'onetags' and 'twotags'."
if __name__ == '__main__':
- print(__doc__)
+ print __doc__
diff --git a/tablib/packages/markup3.py b/tablib/packages/markup3.py
new file mode 100644
index 0000000..1973c00
--- /dev/null
+++ b/tablib/packages/markup3.py
@@ -0,0 +1,484 @@
+# This code is in the public domain, it comes
+# with absolutely no warranty and you can do
+# absolutely whatever you want with it.
+
+__date__ = '17 May 2007'
+__version__ = '1.7'
+__doc__= """
+This is markup.py - a Python module that attempts to
+make it easier to generate HTML/XML from a Python program
+in an intuitive, lightweight, customizable and pythonic way.
+
+The code is in the public domain.
+
+Version: %s as of %s.
+
+Documentation and further info is at http://markup.sourceforge.net/
+
+Please send bug reports, feature requests, enhancement
+ideas or questions to nogradi at gmail dot com.
+
+Installation: drop markup.py somewhere into your Python path.
+""" % ( __version__, __date__ )
+
+import string
+
+class element:
+ """This class handles the addition of a new element."""
+
+ def __init__( self, tag, case='lower', parent=None ):
+ self.parent = parent
+
+ if case == 'lower':
+ self.tag = tag.lower( )
+ else:
+ self.tag = tag.upper( )
+
+ def __call__( self, *args, **kwargs ):
+ if len( args ) > 1:
+ raise ArgumentError( self.tag )
+
+ # if class_ was defined in parent it should be added to every element
+ if self.parent is not None and self.parent.class_ is not None:
+ if 'class_' not in kwargs:
+ kwargs['class_'] = self.parent.class_
+
+ if self.parent is None and len( args ) == 1:
+ x = [ self.render( self.tag, False, myarg, mydict ) for myarg, mydict in _argsdicts( args, kwargs ) ]
+ return '\n'.join( x )
+ elif self.parent is None and len( args ) == 0:
+ x = [ self.render( self.tag, True, myarg, mydict ) for myarg, mydict in _argsdicts( args, kwargs ) ]
+ return '\n'.join( x )
+
+ if self.tag in self.parent.twotags:
+ for myarg, mydict in _argsdicts( args, kwargs ):
+ self.render( self.tag, False, myarg, mydict )
+ elif self.tag in self.parent.onetags:
+ if len( args ) == 0:
+ for myarg, mydict in _argsdicts( args, kwargs ):
+ self.render( self.tag, True, myarg, mydict ) # here myarg is always None, because len( args ) = 0
+ else:
+ raise ClosingError( self.tag )
+ elif self.parent.mode == 'strict_html' and self.tag in self.parent.deptags:
+ raise DeprecationError( self.tag )
+ else:
+ raise InvalidElementError( self.tag, self.parent.mode )
+
+ def render( self, tag, single, between, kwargs ):
+ """Append the actual tags to content."""
+
+ out = "<%s" % tag
+ for key, value in kwargs.items( ):
+ if value is not None: # when value is None that means stuff like <... checked>
+ key = key.strip('_') # strip this so class_ will mean class, etc.
+ if key == 'http_equiv': # special cases, maybe change _ to - overall?
+ key = 'http-equiv'
+ elif key == 'accept_charset':
+ key = 'accept-charset'
+ out = "%s %s=\"%s\"" % ( out, key, escape( value ) )
+ else:
+ out = "%s %s" % ( out, key )
+ if between is not None:
+ out = "%s>%s%s>" % ( out, between, tag )
+ else:
+ if single:
+ out = "%s />" % out
+ else:
+ out = "%s>" % out
+ if self.parent is not None:
+ self.parent.content.append( out )
+ else:
+ return out
+
+ def close( self ):
+ """Append a closing tag unless element has only opening tag."""
+
+ if self.tag in self.parent.twotags:
+ self.parent.content.append( "%s>" % self.tag )
+ elif self.tag in self.parent.onetags:
+ raise ClosingError( self.tag )
+ elif self.parent.mode == 'strict_html' and self.tag in self.parent.deptags:
+ raise DeprecationError( self.tag )
+
+ def open( self, **kwargs ):
+ """Append an opening tag."""
+
+ if self.tag in self.parent.twotags or self.tag in self.parent.onetags:
+ self.render( self.tag, False, None, kwargs )
+ elif self.mode == 'strict_html' and self.tag in self.parent.deptags:
+ raise DeprecationError( self.tag )
+
+class page:
+ """This is our main class representing a document. Elements are added
+ as attributes of an instance of this class."""
+
+ def __init__( self, mode='strict_html', case='lower', onetags=None, twotags=None, separator='\n', class_=None ):
+ """Stuff that effects the whole document.
+
+ mode -- 'strict_html' for HTML 4.01 (default)
+ 'html' alias for 'strict_html'
+ 'loose_html' to allow some deprecated elements
+ 'xml' to allow arbitrary elements
+
+ case -- 'lower' element names will be printed in lower case (default)
+ 'upper' they will be printed in upper case
+
+ onetags -- list or tuple of valid elements with opening tags only
+ twotags -- list or tuple of valid elements with both opening and closing tags
+ these two keyword arguments may be used to select
+ the set of valid elements in 'xml' mode
+ invalid elements will raise appropriate exceptions
+
+ separator -- string to place between added elements, defaults to newline
+
+ class_ -- a class that will be added to every element if defined"""
+
+ valid_onetags = [ "AREA", "BASE", "BR", "COL", "FRAME", "HR", "IMG", "INPUT", "LINK", "META", "PARAM" ]
+ valid_twotags = [ "A", "ABBR", "ACRONYM", "ADDRESS", "B", "BDO", "BIG", "BLOCKQUOTE", "BODY", "BUTTON",
+ "CAPTION", "CITE", "CODE", "COLGROUP", "DD", "DEL", "DFN", "DIV", "DL", "DT", "EM", "FIELDSET",
+ "FORM", "FRAMESET", "H1", "H2", "H3", "H4", "H5", "H6", "HEAD", "HTML", "I", "IFRAME", "INS",
+ "KBD", "LABEL", "LEGEND", "LI", "MAP", "NOFRAMES", "NOSCRIPT", "OBJECT", "OL", "OPTGROUP",
+ "OPTION", "P", "PRE", "Q", "SAMP", "SCRIPT", "SELECT", "SMALL", "SPAN", "STRONG", "STYLE",
+ "SUB", "SUP", "TABLE", "TBODY", "TD", "TEXTAREA", "TFOOT", "TH", "THEAD", "TITLE", "TR",
+ "TT", "UL", "VAR" ]
+ deprecated_onetags = [ "BASEFONT", "ISINDEX" ]
+ deprecated_twotags = [ "APPLET", "CENTER", "DIR", "FONT", "MENU", "S", "STRIKE", "U" ]
+
+ self.header = [ ]
+ self.content = [ ]
+ self.footer = [ ]
+ self.case = case
+ self.separator = separator
+
+ # init( ) sets it to True so we know that