[Python-modules-commits] r31190 - in packages/python-odf/trunk/debian (11 files)
georgesk at users.alioth.debian.org
georgesk at users.alioth.debian.org
Tue Oct 21 09:54:58 UTC 2014
Date: Tuesday, October 21, 2014 @ 09:54:57
Author: georgesk
Revision: 31190
preparing for Python3
Added:
packages/python-odf/trunk/debian/patches/
packages/python-odf/trunk/debian/patches/libsToPython3.patch
packages/python-odf/trunk/debian/patches/series
packages/python-odf/trunk/debian/patches/toPython3.patch
packages/python-odf/trunk/debian/python-odf-doc.install
packages/python-odf/trunk/debian/python-odf.install
packages/python-odf/trunk/debian/python3-odf.install
Modified:
packages/python-odf/trunk/debian/changelog
packages/python-odf/trunk/debian/compat
packages/python-odf/trunk/debian/control
packages/python-odf/trunk/debian/rules
Modified: packages/python-odf/trunk/debian/changelog
===================================================================
--- packages/python-odf/trunk/debian/changelog 2014-10-21 08:34:37 UTC (rev 31189)
+++ packages/python-odf/trunk/debian/changelog 2014-10-21 09:54:57 UTC (rev 31190)
@@ -1,3 +1,16 @@
+python-odf (0.9.7-0.1) UNRELEASED; urgency=medium
+
+ * Non-maintainer upload.
+ * modified the library to work with python3
+ * upgraded Standards-Version to 3.9.5, debhelper to 9
+ * added two new binary packages: python3-odf and python-odf-doc; the last one
+ provides the documentation for Odfpy's API as an opendocument
+ * modified the test routine to run tests with both python 2 and 3.
+ All tests are not passed. testxhtml.py does not appear to work in a
+ predictible way: the number of failures may change when it is run again.
+
+ -- Georges Khaznadar <georgesk at debian.org> Sun, 19 Oct 2014 16:42:00 +0200
+
python-odf (0.9.6-2) unstable; urgency=low
[Jakub Wilk <jwilk at debian.org> Sun, 05 May 2013 16:03:01 +0200]
Modified: packages/python-odf/trunk/debian/compat
===================================================================
--- packages/python-odf/trunk/debian/compat 2014-10-21 08:34:37 UTC (rev 31189)
+++ packages/python-odf/trunk/debian/compat 2014-10-21 09:54:57 UTC (rev 31190)
@@ -1 +1 @@
-8
+9
Modified: packages/python-odf/trunk/debian/control
===================================================================
--- packages/python-odf/trunk/debian/control 2014-10-21 08:34:37 UTC (rev 31189)
+++ packages/python-odf/trunk/debian/control 2014-10-21 09:54:57 UTC (rev 31190)
@@ -3,8 +3,8 @@
Priority: optional
Maintainer: Debian Python Modules Team <python-modules-team at lists.alioth.debian.org>
Uploaders: Thomas Bechtold <thomasbechtold at jpberlin.de>, W. Martin Borgert <debacle at debian.org>
-Standards-Version: 3.9.4
-Build-Depends: debhelper (>= 8), python-all, xmlto
+Standards-Version: 3.9.5
+Build-Depends: debhelper (>= 9.0), python-all, python3-all, xmlto
X-Python-Version: >= 2.7
Homepage: https://joinup.ec.europa.eu/software/odfpy/home
Vcs-Svn: svn://anonscm.debian.org/python-modules/packages/python-odf/trunk/
@@ -12,8 +12,9 @@
Package: python-odf
Architecture: all
+Recommends: python-odf-doc
Depends: ${misc:Depends}, ${python:Depends}
-Description: Odfpy aims to be a complete API for OpenDocument in Python.
+Description: Odfpy aims to be a complete API for OpenDocument in Python2.
Unlike other more convenient APIs, this one is essentially an abstraction
layer just above the XML format. Odfpy is a library to read and write
OpenDocument v. 1.1 files. The main focus has been to prevent the programmer
@@ -25,3 +26,28 @@
all ODF constructions, but could be improved in its understanding of data
types. Take a look at the Getting Started page then consult the Reference
Manual.
+
+Package: python3-odf
+Architecture: all
+Recommends: python-odf-doc
+Conflicts: python-odf (<< 0.9.7)
+Depends: ${misc:Depends}, ${python:Depends}, python3
+Description: Odfpy aims to be a complete API for OpenDocument in Python3.
+ Unlike other more convenient APIs, this one is essentially an abstraction
+ layer just above the XML format. Odfpy is a library to read and write
+ OpenDocument v. 1.1 files. The main focus has been to prevent the programmer
+ from creating invalid documents. It has checks that raise an exception if the
+ programmer adds an invalid element, adds an attribute unknown to the grammar,
+ forgets to add a required attribute or adds text to an element that doesn't
+ allow it. These checks and the API itself were generated from the RelaxNG
+ schema, and then hand-edited. Therefore the API is complete and can handle
+ all ODF constructions, but could be improved in its understanding of data
+ types. Take a look at the Getting Started page then consult the Reference
+ Manual.
+
+Package: python-odf-doc
+Architecture: all
+Section: doc
+Depends: ${misc:Depends}
+Description: documentation files for python-odf and python3-odf
+ Odfpy is a library to read and write OpenDocument v. 1.1 files.
Added: packages/python-odf/trunk/debian/patches/libsToPython3.patch
===================================================================
--- packages/python-odf/trunk/debian/patches/libsToPython3.patch (rev 0)
+++ packages/python-odf/trunk/debian/patches/libsToPython3.patch 2014-10-21 09:54:57 UTC (rev 31190)
@@ -0,0 +1,1092 @@
+Index: python-odf-0.9.7/odf/attrconverters.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/attrconverters.py
++++ python-odf-0.9.7/odf/attrconverters.py
+@@ -17,6 +17,9 @@
+ #
+ # Contributor(s):
+ #
++
++import sys, os.path
++sys.path.append(os.path.dirname(__file__))
+ from namespaces import *
+ import re, types
+
+@@ -29,7 +32,7 @@ def make_NCName(arg):
+ return arg
+
+ def cnv_anyURI(attribute, arg, element):
+- return unicode(arg)
++ return str(arg)
+
+ def cnv_boolean(attribute, arg, element):
+ """ XML Schema Part 2: Datatypes Second Edition
+@@ -40,7 +43,7 @@ def cnv_boolean(attribute, arg, element)
+ return "false"
+ if str(arg).lower() in ("1","true","yes"):
+ return "true"
+- raise ValueError, "'%s' not allowed as Boolean value for %s" % (str(arg), attribute)
++ raise ValueError( "'%s' not allowed as Boolean value for %s" % (str(arg), attribute))
+
+ # Potentially accept color values
+ def cnv_color(attribute, arg, element):
+@@ -52,12 +55,12 @@ def cnv_color(attribute, arg, element):
+ def cnv_configtype(attribute, arg, element):
+ if str(arg) not in ("boolean", "short", "int", "long",
+ "double", "string", "datetime", "base64Binary"):
+- raise ValueError, "'%s' not allowed" % str(arg)
++ raise ValueError( "'%s' not allowed" % str(arg))
+ return str(arg)
+
+ def cnv_data_source_has_labels(attribute, arg, element):
+ if str(arg) not in ("none","row","column","both"):
+- raise ValueError, "'%s' not allowed" % str(arg)
++ raise ValueError( "'%s' not allowed" % str(arg))
+ return str(arg)
+
+ # Understand different date formats
+@@ -83,19 +86,19 @@ def cnv_family(attribute, arg, element):
+ """ A style family """
+ if str(arg) not in ("text", "paragraph", "section", "ruby", "table", "table-column", "table-row", "table-cell",
+ "graphic", "presentation", "drawing-page", "chart"):
+- raise ValueError, "'%s' not allowed" % str(arg)
++ raise ValueError( "'%s' not allowed" % str(arg))
+ return str(arg)
+
+ def __save_prefix(attribute, arg, element):
+ prefix = arg.split(':',1)[0]
+ if prefix == arg:
+- return unicode(arg)
++ return str(arg)
+ namespace = element.get_knownns(prefix)
+ if namespace is None:
+- #raise ValueError, "'%s' is an unknown prefix" % str(prefix)
+- return unicode(arg)
++ #raise ValueError( "'%s' is an unknown prefix" % str(prefix))
++ return str(arg)
+ p = element.get_nsprefix(namespace)
+- return unicode(arg)
++ return str(arg)
+
+ def cnv_formula(attribute, arg, element):
+ """ A string containing a formula. Formulas do not have a predefined syntax, but the string should
+@@ -116,7 +119,7 @@ def cnv_integer(attribute, arg, element)
+
+ def cnv_legend_position(attribute, arg, element):
+ if str(arg) not in ("start", "end", "top", "bottom", "top-start", "bottom-start", "top-end", "bottom-end"):
+- raise ValueError, "'%s' not allowed" % str(arg)
++ raise ValueError( "'%s' not allowed" % str(arg))
+ return str(arg)
+
+ pattern_length = re.compile(r'-?([0-9]+(\.[0-9]*)?|\.[0-9]+)((cm)|(mm)|(in)|(pt)|(pc)|(px))')
+@@ -127,7 +130,7 @@ def cnv_length(attribute, arg, element):
+ """
+ global pattern_length
+ if not pattern_length.match(arg):
+- raise ValueError, "'%s' is not a valid length" % arg
++ raise ValueError( "'%s' is not a valid length" % arg)
+ return arg
+
+ def cnv_lengthorpercent(attribute, arg, element):
+@@ -137,17 +140,17 @@ def cnv_lengthorpercent(attribute, arg,
+ try: return cnv_percent(attribute, arg, element)
+ except: failed = True
+ if failed:
+- raise ValueError, "'%s' is not a valid length or percent" % arg
++ raise ValueError( "'%s' is not a valid length or percent" % arg)
+ return arg
+
+ def cnv_metavaluetype(attribute, arg, element):
+ if str(arg) not in ("float", "date", "time", "boolean", "string"):
+- raise ValueError, "'%s' not allowed" % str(arg)
++ raise ValueError( "'%s' not allowed" % str(arg))
+ return str(arg)
+
+ def cnv_major_minor(attribute, arg, element):
+ if arg not in ('major','minor'):
+- raise ValueError, "'%s' is not either 'minor' or 'major'" % arg
++ raise ValueError( "'%s' is not either 'minor' or 'major'" % arg)
+
+ pattern_namespacedToken = re.compile(r'[0-9a-zA-Z_]+:[0-9a-zA-Z._\-]+')
+
+@@ -155,14 +158,15 @@ def cnv_namespacedToken(attribute, arg,
+ global pattern_namespacedToken
+
+ if not pattern_namespacedToken.match(arg):
+- raise ValueError, "'%s' is not a valid namespaced token" % arg
++ raise ValueError( "'%s' is not a valid namespaced token" % arg)
+ return __save_prefix(attribute, arg, element)
+
+ def cnv_NCName(attribute, arg, element):
+ """ NCName is defined in http://www.w3.org/TR/REC-xml-names/#NT-NCName
+ Essentially an XML name minus ':'
+ """
+- if type(arg) in types.StringTypes:
++ #if type(arg) in types.StringTypes:
++ if (sys.version_info.major==3 and isinstance(arg, str)) or type(arg) in types.StringTypes:
+ return make_NCName(arg)
+ else:
+ return arg.getAttrNS(STYLENS, 'name')
+@@ -199,7 +203,7 @@ pattern_percent = re.compile(r'-?([0-9]+
+ def cnv_percent(attribute, arg, element):
+ global pattern_percent
+ if not pattern_percent.match(arg):
+- raise ValueError, "'%s' is not a valid length" % arg
++ raise ValueError( "'%s' is not a valid length" % arg)
+ return arg
+
+ # Real one doesn't allow floating point values
+@@ -207,26 +211,29 @@ pattern_points = re.compile(r'-?[0-9]+,-
+ #pattern_points = re.compile(r'-?[0-9.]+,-?[0-9.]+([ ]+-?[0-9.]+,-?[0-9.]+)*')
+ def cnv_points(attribute, arg, element):
+ global pattern_points
+- if type(arg) in types.StringTypes:
++ if (sys.version_info.major==3 and isinstance(arg, str)) or (sys.version_info.major==2 and type(arg) in types.StringTypes):
+ if not pattern_points.match(arg):
+- raise ValueError, "x,y are separated by a comma and the points are separated by white spaces"
++ raise ValueError( "x,y are separated by a comma and the points are separated by white spaces")
+ return arg
+ else:
+ try:
+ strarg = ' '.join([ "%d,%d" % p for p in arg])
+ except:
+- raise ValueError, "Points must be string or [(0,0),(1,1)] - not %s" % arg
++ raise ValueError( "Points must be string or [(0,0),(1,1)] - not %s" % arg)
+ return strarg
+
+ def cnv_positiveInteger(attribute, arg, element):
+ return str(arg)
+
+ def cnv_string(attribute, arg, element):
+- return unicode(arg)
++ try:
++ return unicode(arg)
++ except NameError:
++ return str(arg)
+
+ def cnv_textnoteclass(attribute, arg, element):
+ if str(arg) not in ("footnote", "endnote"):
+- raise ValueError, "'%s' not allowed" % str(arg)
++ raise ValueError( "'%s' not allowed" % str(arg))
+ return str(arg)
+
+ # Understand different time formats
+@@ -241,12 +248,12 @@ pattern_viewbox = re.compile(r'-?[0-9]+(
+ def cnv_viewbox(attribute, arg, element):
+ global pattern_viewbox
+ if not pattern_viewbox.match(arg):
+- raise ValueError, "viewBox must be four integers separated by whitespaces"
++ raise ValueError( "viewBox must be four integers separated by whitespaces")
+ return arg
+
+ def cnv_xlinkshow(attribute, arg, element):
+ if str(arg) not in ("new", "replace", "embed"):
+- raise ValueError, "'%s' not allowed" % str(arg)
++ raise ValueError( "'%s' not allowed" % str(arg))
+ return str(arg)
+
+
+@@ -1486,5 +1493,8 @@ class AttrConverters:
+ conversion = attrconverters.get((attribute, None), None)
+ if conversion is not None:
+ return conversion(attribute, value, element)
+- return unicode(value)
++ try:
++ return unicode(value)
++ except:
++ return str(value)
+
+Index: python-odf-0.9.7/odf/draw.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/draw.py
++++ python-odf-0.9.7/odf/draw.py
+@@ -18,6 +18,8 @@
+ # Contributor(s):
+ #
+
++import sys, os.path
++sys.path.append(os.path.dirname(__file__))
+ from namespaces import DRAWNS, STYLENS, PRESENTATIONNS
+ from element import Element
+
+@@ -30,7 +32,7 @@ def StyleRefElement(stylename=None, clas
+ elif f == 'presentation':
+ qattrs[(PRESENTATIONNS,u'style-name')]= stylename
+ else:
+- raise ValueError, "Style's family must be either 'graphic' or 'presentation'"
++ raise ValueError( "Style's family must be either 'graphic' or 'presentation'")
+ if classnames is not None:
+ f = classnames[0].getAttrNS(STYLENS, 'family')
+ if f == 'graphic':
+@@ -38,12 +40,12 @@ def StyleRefElement(stylename=None, clas
+ elif f == 'presentation':
+ qattrs[(PRESENTATIONNS,u'class-names')]= classnames
+ else:
+- raise ValueError, "Style's family must be either 'graphic' or 'presentation'"
++ raise ValueError( "Style's family must be either 'graphic' or 'presentation'")
+ return Element(qattributes=qattrs, **args)
+
+ def DrawElement(name=None, **args):
+ e = Element(name=name, **args)
+- if not args.has_key('displayname'):
++ if 'displayname' not in args:
+ e.setAttrNS(DRAWNS,'display-name', name)
+ return e
+
+Index: python-odf-0.9.7/odf/element.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/element.py
++++ python-odf-0.9.7/odf/element.py
+@@ -22,6 +22,8 @@
+ # Note: This script has copied a lot of text from xml.dom.minidom.
+ # Whatever license applies to that file also applies to this file.
+ #
++import sys, os.path
++sys.path.append(os.path.dirname(__file__))
+ import xml.dom
+ from xml.dom.minicompat import *
+ from namespaces import nsdict
+@@ -79,6 +81,11 @@ def _nssplit(qualifiedName):
+ def _nsassign(namespace):
+ return nsdict.setdefault(namespace,"ns" + str(len(nsdict)))
+
++try:
++ StandardError
++except NameError:
++ StandardError=Exception
++
+ # Exceptions
+ class IllegalChild(StandardError):
+ """ Complains if you add an element to a parent where it is not allowed """
+@@ -116,7 +123,7 @@ class Node(xml.dom.Node):
+ If refChild is null, insert newChild at the end of the list of children.
+ """
+ if newChild.nodeType not in self._child_node_types:
+- raise IllegalChild, "%s cannot be child of %s" % (newChild.tagName, self.tagName)
++ raise IllegalChild( "%s cannot be child of %s" % (newChild.tagName, self.tagName))
+ if newChild.parentNode is not None:
+ newChild.parentNode.removeChild(newChild)
+ if refChild is None:
+@@ -148,7 +155,7 @@ class Node(xml.dom.Node):
+ ### The DOM does not clearly specify what to return in this case
+ return newChild
+ if newChild.nodeType not in self._child_node_types:
+- raise IllegalChild, "<%s> is not allowed in %s" % ( newChild.tagName, self.tagName)
++ raise IllegalChild( "<%s> is not allowed in %s" % ( newChild.tagName, self.tagName))
+ if newChild.parentNode is not None:
+ newChild.parentNode.removeChild(newChild)
+ _append_child(self, newChild)
+@@ -245,7 +252,10 @@ class Text(Childless, Node):
+ self.data = data
+
+ def __str__(self):
+- return self.data.encode()
++ if sys.version_info.major ==3:
++ return self.data
++ else:
++ return self.data.encode()
+
+ def __unicode__(self):
+ return self.data
+@@ -253,9 +263,12 @@ class Text(Childless, Node):
+ def toXml(self,level,f):
+ """ Write XML in UTF-8 """
+ if self.data:
+- f.write(_escape(unicode(self.data).encode('utf-8')))
++ if sys.version_info.major == 3:
++ f.write(_escape(self.data))
++ else:
++ f.write(_escape(unicode(self.data).encode('utf-8')))
+
+-class CDATASection(Childless, Text):
++class CDATASection(Text, Childless):
+ nodeType = Node.CDATA_SECTION_NODE
+
+ def toXml(self,level,f):
+@@ -324,7 +337,7 @@ class Element(Node):
+ if required:
+ for r in required:
+ if self.getAttrNS(r[0],r[1]) is None:
+- raise AttributeError, "Required attribute missing: %s in <%s>" % (r[1].lower().replace('-',''), self.tagName)
++ raise AttributeError( "Required attribute missing: %s in <%s>" % (r[1].lower().replace('-',''), self.tagName))
+
+ def get_knownns(self, prefix):
+ """ Odfpy maintains a list of known namespaces. In some cases a prefix is used, and
+@@ -341,7 +354,7 @@ class Element(Node):
+ """
+ if namespace is None: namespace = ""
+ prefix = _nsassign(namespace)
+- if not self.namespaces.has_key(namespace):
++ if not namespace in self.namespaces:
+ self.namespaces[namespace] = prefix
+ return prefix
+
+@@ -360,7 +373,7 @@ class Element(Node):
+ """
+ if check_grammar and self.allowed_children is not None:
+ if element.qname not in self.allowed_children:
+- raise IllegalChild, "<%s> is not allowed in <%s>" % ( element.tagName, self.tagName)
++ raise IllegalChild( "<%s> is not allowed in <%s>" % ( element.tagName, self.tagName))
+ self.appendChild(element)
+ self._setOwnerDoc(element)
+ if self.ownerDocument:
+@@ -371,7 +384,7 @@ class Element(Node):
+ Setting check_grammar=False turns off grammar checking
+ """
+ if check_grammar and self.qname not in grammar.allows_text:
+- raise IllegalText, "The <%s> element does not allow text" % self.tagName
++ raise IllegalText( "The <%s> element does not allow text" % self.tagName)
+ else:
+ if text != '':
+ self.appendChild(Text(text))
+@@ -381,7 +394,7 @@ class Element(Node):
+ Setting check_grammar=False turns off grammar checking
+ """
+ if check_grammar and self.qname not in grammar.allows_text:
+- raise IllegalText, "The <%s> element does not allow text" % self.tagName
++ raise IllegalText( "The <%s> element does not allow text" % self.tagName)
+ else:
+ self.appendChild(CDATASection(cdata))
+
+@@ -393,12 +406,12 @@ class Element(Node):
+ prefix, localname = attr
+ self.removeAttrNS(prefix, localname)
+ else:
+- raise AttributeError, "Unable to add simple attribute - use (namespace, localpart)"
++ raise AttributeError( "Unable to add simple attribute - use (namespace, localpart)")
+ else:
+ # Construct a list of allowed arguments
+ allowed_args = [ a[1].lower().replace('-','') for a in allowed_attrs]
+ if check_grammar and attr not in allowed_args:
+- raise AttributeError, "Attribute %s is not allowed in <%s>" % ( attr, self.tagName)
++ raise AttributeError( "Attribute %s is not allowed in <%s>" % ( attr, self.tagName))
+ i = allowed_args.index(attr)
+ self.removeAttrNS(allowed_attrs[i][0], allowed_attrs[i][1])
+
+@@ -416,12 +429,12 @@ class Element(Node):
+ prefix, localname = attr
+ self.setAttrNS(prefix, localname, value)
+ else:
+- raise AttributeError, "Unable to add simple attribute - use (namespace, localpart)"
++ raise AttributeError( "Unable to add simple attribute - use (namespace, localpart)")
+ else:
+ # Construct a list of allowed arguments
+ allowed_args = [ a[1].lower().replace('-','') for a in allowed_attrs]
+ if check_grammar and attr not in allowed_args:
+- raise AttributeError, "Attribute %s is not allowed in <%s>" % ( attr, self.tagName)
++ raise AttributeError( "Attribute %s is not allowed in <%s>" % ( attr, self.tagName))
+ i = allowed_args.index(attr)
+ self.setAttrNS(allowed_attrs[i][0], allowed_attrs[i][1], value)
+
+@@ -435,7 +448,7 @@ class Element(Node):
+ allowed_attrs = self.allowed_attributes()
+ prefix = self.get_nsprefix(namespace)
+ # if allowed_attrs and (namespace, localpart) not in allowed_attrs:
+-# raise AttributeError, "Attribute %s:%s is not allowed in element <%s>" % ( prefix, localpart, self.tagName)
++# raise AttributeError( "Attribute %s:%s is not allowed in element <%s>" % ( prefix, localpart, self.tagName))
+ c = AttrConverters()
+ self.attributes[(namespace, localpart)] = c.convert((namespace, localpart), value, self)
+
+@@ -455,7 +468,7 @@ class Element(Node):
+ prefix, localname = attr
+ return self.getAttrNS(prefix, localname)
+ else:
+- raise AttributeError, "Unable to get simple attribute - use (namespace, localpart)"
++ raise AttributeError( "Unable to get simple attribute - use (namespace, localpart)")
+ else:
+ # Construct a list of allowed arguments
+ allowed_args = [ a[1].lower().replace('-','') for a in allowed_attrs]
+@@ -469,7 +482,10 @@ class Element(Node):
+ f.write(' xmlns:' + prefix + '="'+ _escape(str(namespace))+'"')
+ for qname in self.attributes.keys():
+ prefix = self.get_nsprefix(qname[0])
+- f.write(' '+_escape(str(prefix+':'+qname[1]))+'='+_quoteattr(unicode(self.attributes[qname]).encode('utf-8')))
++ if sys.version_info.major==3:
++ f.write(' '+_escape(str(prefix+':'+qname[1]))+'='+_quoteattr(self.attributes[qname]))
++ else:
++ f.write(' '+_escape(str(prefix+':'+qname[1]))+'='+_quoteattr(unicode(self.attributes[qname]).encode('utf-8')))
+ f.write('>')
+
+ def write_close_tag(self, level, f):
+@@ -483,14 +499,17 @@ class Element(Node):
+ f.write(' xmlns:' + prefix + '="'+ _escape(str(namespace))+'"')
+ for qname in self.attributes.keys():
+ prefix = self.get_nsprefix(qname[0])
+- f.write(' '+_escape(str(prefix+':'+qname[1]))+'='+_quoteattr(unicode(self.attributes[qname]).encode('utf-8')))
++ if sys.version_info.major==3:
++ f.write(' '+_escape(str(prefix+':'+qname[1]))+'='+_quoteattr(self.attributes[qname]))
++ else:
++ f.write(u' '+_escape(str(prefix+':'+qname[1]))+'='+_quoteattr(unicode(self.attributes[qname])))
+ if self.childNodes:
+- f.write('>')
++ f.write(u'>')
+ for element in self.childNodes:
+ element.toXml(level+1,f)
+- f.write('</'+self.tagName+'>')
++ f.write(u'</'+self.tagName+'>')
+ else:
+- f.write('/>')
++ f.write(u'/>')
+
+ def _getElementsByObj(self, obj, accumulator):
+ if self.qname == obj.qname:
+Index: python-odf-0.9.7/odf/load.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/load.py
++++ python-odf-0.9.7/odf/load.py
+@@ -29,7 +29,10 @@ from xml.sax.xmlreader import InputSourc
+ import xml.sax.saxutils
+ from element import Element
+ from namespaces import OFFICENS
+-from cStringIO import StringIO
++try:
++ from cStringIO import StringIO
++except ImportError:
++ from io import StringIO
+
+ #
+ # Parse the XML files
+@@ -74,8 +77,8 @@ class LoadParser(handler.ContentHandler)
+ try:
+ e = Element(qname = tag, qattributes=attrdict, check_grammar=False)
+ self.curr = e
+- except AttributeError, v:
+- print "Error: %s" % v
++ except AttributeError as v:
++ print ("Error: %s" % v)
+
+ if tag == (OFFICENS, 'automatic-styles'):
+ e = self.doc.automaticstyles
+Index: python-odf-0.9.7/odf/manifest.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/manifest.py
++++ python-odf-0.9.7/odf/manifest.py
+@@ -20,6 +20,9 @@
+ #
+ #
+
++import sys, os.path
++sys.path.append(os.path.dirname(__file__))
++
+ from namespaces import MANIFESTNS
+ from element import Element
+
+Index: python-odf-0.9.7/odf/odf2xhtml.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/odf2xhtml.py
++++ python-odf-0.9.7/odf/odf2xhtml.py
+@@ -20,13 +20,15 @@
+ #
+ #import pdb
+ #pdb.set_trace()
++from __future__ import absolute_import
++import sys
+ from xml.sax import handler
+ from xml.sax.saxutils import escape, quoteattr
+ from xml.dom import Node
+
+-from opendocument import load
++from .opendocument import load
+
+-from namespaces import ANIMNS, CHARTNS, CONFIGNS, DCNS, DR3DNS, DRAWNS, FONS, \
++from .namespaces import ANIMNS, CHARTNS, CONFIGNS, DCNS, DR3DNS, DRAWNS, FONS, \
+ FORMNS, MATHNS, METANS, NUMBERNS, OFFICENS, PRESENTATIONNS, SCRIPTNS, \
+ SMILNS, STYLENS, SVGNS, TABLENS, TEXTNS, XLINKNS
+
+@@ -215,7 +217,7 @@ class StyleToCSS:
+ sdict['right'] = "0";
+ else: # No wrapping
+ sdict['margin-left'] = "auto"
+- sdict['margin-right'] = "0px"
++ sdict['margin-right'] = "0cm"
+ elif hpos in ("left", "inside"):
+ if wrap in ( "right", "parallel","dynamic"):
+ sdict['float'] = "left"
+@@ -224,14 +226,14 @@ class StyleToCSS:
+ sdict['top'] = "0"
+ sdict['left'] = "0"
+ else: # No wrapping
+- sdict['margin-left'] = "0px"
++ sdict['margin-left'] = "0cm"
+ sdict['margin-right'] = "auto"
+ elif hpos in ("from-left", "from-inside"):
+ if wrap in ( "right", "parallel"):
+ sdict['float'] = "left"
+ else:
+ sdict['position'] = "relative" # No wrapping
+- if ruleset.has_key( (SVGNS,'x') ):
++ if (SVGNS,'x') in ruleset:
+ sdict['left'] = ruleset[(SVGNS,'x')]
+
+ def c_page_width(self, ruleset, sdict, rule, val):
+@@ -291,7 +293,7 @@ class TagStack:
+ def rfindattr(self, attr):
+ """ Find a tag with the given attribute """
+ for tag, attrs in self.stack:
+- if attrs.has_key(attr):
++ if attr in attrs:
+ return attrs[attr]
+ return None
+ def count_tags(self, tag):
+@@ -590,7 +592,7 @@ class ODF2XHTML(handler.ContentHandler):
+
+ def get_anchor(self, name):
+ """ Create a unique anchor id for a href name """
+- if not self.anchors.has_key(name):
++ if name not in self.anchors:
+ self.anchors[name] = "anchor%03d" % (len(self.anchors) + 1)
+ return self.anchors.get(name)
+
+@@ -650,13 +652,13 @@ class ODF2XHTML(handler.ContentHandler):
+ style = ''
+ else:
+ style = "position: absolute;"
+- if attrs.has_key( (SVGNS,"width") ):
++ if (SVGNS,"width")in attrs:
+ style = style + "width:" + attrs[(SVGNS,"width")] + ";"
+- if attrs.has_key( (SVGNS,"height") ):
++ if (SVGNS,"height") in attrs:
+ style = style + "height:" + attrs[(SVGNS,"height")] + ";"
+- if attrs.has_key( (SVGNS,"x") ):
++ if (SVGNS,"x") in attrs:
+ style = style + "left:" + attrs[(SVGNS,"x")] + ";"
+- if attrs.has_key( (SVGNS,"y") ):
++ if (SVGNS,"y") in attrs:
+ style = style + "top:" + attrs[(SVGNS,"y")] + ";"
+ if self.generate_css:
+ self.opentag(htmltag, {'class': name, 'style': style})
+@@ -686,13 +688,13 @@ class ODF2XHTML(handler.ContentHandler):
+ style = ''
+ else:
+ style = "position:absolute;"
+- if attrs.has_key( (SVGNS,"width") ):
++ if (SVGNS,"width") in attrs:
+ style = style + "width:" + attrs[(SVGNS,"width")] + ";"
+- if attrs.has_key( (SVGNS,"height") ):
++ if (SVGNS,"height") in attrs:
+ style = style + "height:" + attrs[(SVGNS,"height")] + ";"
+- if attrs.has_key( (SVGNS,"x") ):
++ if (SVGNS,"x") in attrs:
+ style = style + "left:" + attrs[(SVGNS,"x")] + ";"
+- if attrs.has_key( (SVGNS,"y") ):
++ if (SVGNS,"y") in attrs:
+ style = style + "top:" + attrs[(SVGNS,"y")] + ";"
+ if self.generate_css:
+ self.opentag(htmltag, {'class': name, 'style': style})
+@@ -775,7 +777,7 @@ class ODF2XHTML(handler.ContentHandler):
+
+ def s_draw_textbox(self, tag, attrs):
+ style = ''
+- if attrs.has_key( (FONS,"min-height") ):
++ if (FONS,"min-height") in attrs:
+ style = style + "min-height:" + attrs[(FONS,"min-height")] + ";"
+ self.opentag('div')
+ # self.opentag('div', {'style': style})
+@@ -808,14 +810,14 @@ ol, ul { padding-left: 2em; }
+ for name in self.stylestack:
+ styles = self.styledict.get(name)
+ # Preload with the family's default style
+- if styles.has_key('__style-family') and self.styledict.has_key(styles['__style-family']):
++ if '__style-family'in styles and styles['__style-family'] in self.styledict:
+ familystyle = self.styledict[styles['__style-family']].copy()
+ del styles['__style-family']
+ for style, val in styles.items():
+ familystyle[style] = val
+ styles = familystyle
+ # Resolve the remaining parent styles
+- while styles.has_key('__parent-style-name') and self.styledict.has_key(styles['__parent-style-name']):
++ while '__parent-style-name' in styles and styles['__parent-style-name'] in self.styledict:
+ parentstyle = self.styledict[styles['__parent-style-name']].copy()
+ del styles['__parent-style-name']
+ for style, val in styles.items():
+@@ -1007,7 +1009,7 @@ ol, ul { padding-left: 2em; }
+ pagelayout = attrs.get( (STYLENS,'page-layout-name'), None)
+ if pagelayout:
+ pagelayout = ".PL-" + pagelayout
+- if self.styledict.has_key( pagelayout ):
++ if pagelayout in self.styledict:
+ styles = self.styledict[pagelayout]
+ for style, val in styles.items():
+ self.styledict[self.currentstyle][style] = val
+@@ -1037,7 +1039,7 @@ ol, ul { padding-left: 2em; }
+ parent = attrs.get( (STYLENS,'parent-style-name') )
+ self.currentstyle = special_styles.get(name,"."+name)
+ self.stylestack.append(self.currentstyle)
+- if not self.styledict.has_key(self.currentstyle):
++ if self.currentstyle not in self.styledict:
+ self.styledict[self.currentstyle] = {}
+
+ self.styledict[self.currentstyle]['__style-family'] = htmlfamily
+@@ -1046,7 +1048,7 @@ ol, ul { padding-left: 2em; }
+ if parent:
+ parent = "%s-%s" % (sfamily, parent)
+ parent = special_styles.get(parent, "."+parent)
+- if self.styledict.has_key( parent ):
++ if parent in self.styledict:
+ styles = self.styledict[parent]
+ for style, val in styles.items():
+ self.styledict[self.currentstyle][style] = val
+@@ -1107,7 +1109,7 @@ ol, ul { padding-left: 2em; }
+ htmlattrs = {}
+ if c:
+ htmlattrs['class'] = "TC-%s" % c.replace(".","_")
+- for x in xrange(repeated):
++ for x in range(repeated):
+ self.emptytag('col', htmlattrs)
+ self.purgedata()
+
+@@ -1324,7 +1326,10 @@ ol, ul { padding-left: 2em; }
+ # self.writeout( escape(mark) )
+ # Since HTML only knows about endnotes, there is too much risk that the
+ # marker is reused in the source. Therefore we force numeric markers
+- self.writeout(unicode(self.currentnote))
++ if sys.version_info.major==3:
++ self.writeout(self.currentnote)
++ else:
++ self.writeout(unicode(self.currentnote))
+ self.closetag('sup')
+ self.closetag('a')
+
+@@ -1363,7 +1368,7 @@ ol, ul { padding-left: 2em; }
+ We use so we can send the output through an XML parser if we desire to
+ """
+ c = attrs.get( (TEXTNS,'c'),"1")
+- for x in xrange(int(c)):
++ for x in range(int(c)):
+ self.writeout(' ')
+
+ def s_text_span(self, tag, attrs):
+@@ -1420,6 +1425,10 @@ ol, ul { padding-left: 2em; }
+ """
+ self.lines = []
+ self._wfunc = self._wlines
++ try:
++ basestring
++ except NameError:
++ basestring = str
+ if isinstance(odffile, basestring):
+ self.document = load(odffile)
+ else:
+@@ -1433,7 +1442,10 @@ ol, ul { padding-left: 2em; }
+ self._walknode(c)
+ self.endElementNS(node.qname, node.tagName)
+ if node.nodeType == Node.TEXT_NODE or node.nodeType == Node.CDATA_SECTION_NODE:
+- self.characters(unicode(node))
++ if sys.version_info.major==3:
++ self.characters(str(node))
++ else:
++ self.characters(unicode(node))
+
+
+ def odf2xhtml(self, odffile):
+Index: python-odf-0.9.7/odf/odfmanifest.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/odfmanifest.py
++++ python-odf-0.9.7/odf/odfmanifest.py
+@@ -18,13 +18,16 @@
+ #
+ # Contributor(s):
+ #
+-
++from __future__ import print_function
+ # This script lists the content of the manifest.xml file
+ import zipfile
+ from xml.sax import make_parser,handler
+ from xml.sax.xmlreader import InputSource
+ import xml.sax.saxutils
+-from cStringIO import StringIO
++try:
++ from cStringIO import StringIO
++except ImportError:
++ from io import StringIO
+
+ MANIFESTNS="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0"
+
+@@ -96,6 +99,8 @@ def manifestlist(manifestxml):
+ parser.setErrorHandler(handler.ErrorHandler())
+
+ inpsrc = InputSource()
++ if not isinstance(manifestxml, str):
++ manifestxml=manifestxml.decode("utf-8")
+ inpsrc.setByteStream(StringIO(manifestxml))
+ parser.parse(inpsrc)
+
+@@ -111,5 +116,5 @@ if __name__ == "__main__":
+ import sys
+ result = odfmanifest(sys.argv[1])
+ for file in result.values():
+- print "%-40s %-40s" % (file['media-type'], file['full-path'])
++ print ("%-40s %-40s" % (file['media-type'], file['full-path']))
+
+Index: python-odf-0.9.7/odf/opendocument.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/opendocument.py
++++ python-odf-0.9.7/odf/opendocument.py
+@@ -17,24 +17,34 @@
+ #
+ # Contributor(s):
+ #
++from __future__ import absolute_import
+
+ __doc__="""Use OpenDocument to generate your documents."""
+
+-import zipfile, time, sys, mimetypes, copy
+-from cStringIO import StringIO
+-from namespaces import *
+-import manifest, meta
+-from office import *
++import zipfile, time, sys, mimetypes, copy, os.path
++sys.path.append(os.path.dirname(__file__))
++
++try:
++ from cStringIO import StringIO
++except ImportError:
++ from io import StringIO
++from .namespaces import *
++import manifest
++import meta
++from .office import *
+ import element
+-from attrconverters import make_NCName
++from .attrconverters import make_NCName
+ from xml.sax.xmlreader import InputSource
+-from odfmanifest import manifestlist
++from .odfmanifest import manifestlist
+
+ __version__= TOOLSVERSION
+
+ _XMLPROLOGUE = u"<?xml version='1.0' encoding='UTF-8'?>\n"
+
+-UNIXPERMS = 0100644 << 16L # -rw-r--r--
++########### the following syntax is invalid for Python3 ##############
++# UNIXPERMS = 0100644 << 16L # -rw-r--r--
++######################################################################
++UNIXPERMS = 2175008768 # same value as 0100644 << 16L == -rw-r--r--
+
+ IS_FILENAME = 0
+ IS_IMAGE = 1
+@@ -124,13 +134,13 @@ class OpenDocument:
+ def build_caches(self, element):
+ """ Called from element.py
+ """
+- if not self.element_dict.has_key(element.qname):
++ if element.qname not in self.element_dict:
+ self.element_dict[element.qname] = []
+ self.element_dict[element.qname].append(element)
+ if element.qname == (STYLENS, u'style'):
+ self.__register_stylename(element) # Add to style dictionary
+ styleref = element.getAttrNS(TEXTNS,u'style-name')
+- if styleref is not None and self._styles_ooo_fix.has_key(styleref):
++ if styleref is not None and styleref in self._styles_ooo_fix:
+ element.setAttrNS(TEXTNS,u'style-name', self._styles_ooo_fix[styleref])
+
+ def __register_stylename(self, element):
+@@ -142,7 +152,7 @@ class OpenDocument:
+ if name is None:
+ return
+ if element.parentNode.qname in ((OFFICENS,u'styles'), (OFFICENS,u'automatic-styles')):
+- if self._styles_dict.has_key(name):
++ if name in self._styles_dict:
+ newname = 'M'+name # Rename style
+ self._styles_ooo_fix[name] = newname
+ # From here on all references to the old name will refer to the new one
+@@ -421,7 +431,7 @@ class OpenDocument:
+ zi = zipfile.ZipInfo('mimetype', self._now)
+ zi.compress_type = zipfile.ZIP_STORED
+ zi.external_attr = UNIXPERMS
+- self._z.writestr(zi, self.mimetype)
++ self._z.writestr(zi, self.mimetype.encode("utf-8"))
+
+ self._saveXmlObjects(self,"")
+
+@@ -441,7 +451,10 @@ class OpenDocument:
+ for op in self._extra:
+ if op.filename == "META-INF/documentsignatures.xml": continue # Don't save signatures
+ self.manifest.addElement(manifest.FileEntry(fullpath=op.filename, mediatype=op.mediatype))
+- zi = zipfile.ZipInfo(op.filename.encode('utf-8'), self._now)
++ if sys.version_info.major==3:
++ zi = zipfile.ZipInfo(op.filename, self._now)
++ else:
++ zi = zipfile.ZipInfo(op.filename.encode('utf-8'), self._now)
+ zi.compress_type = zipfile.ZIP_DEFLATED
+ zi.external_attr = UNIXPERMS
+ if op.content is not None:
+@@ -585,7 +598,7 @@ def __loadxmlparts(z, manifest, doc, obj
+ from xml.sax import make_parser, handler
+
+ for xmlfile in (objectpath+'settings.xml', objectpath+'meta.xml', objectpath+'content.xml', objectpath+'styles.xml'):
+- if not manifest.has_key(xmlfile):
++ if xmlfile not in manifest:
+ continue
+ try:
+ xmlpart = z.read(xmlfile)
+@@ -597,10 +610,12 @@ def __loadxmlparts(z, manifest, doc, obj
+ parser.setErrorHandler(handler.ErrorHandler())
+
+ inpsrc = InputSource()
++ if not isinstance(xmlpart, str):
++ xmlpart=xmlpart.decode("utf-8")
+ inpsrc.setByteStream(StringIO(xmlpart))
+ parser.parse(inpsrc)
+ del doc._parsing
+- except KeyError, v: pass
++ except KeyError as v: pass
+
+ def load(odffile):
+ """ Load an ODF file into memory
+Index: python-odf-0.9.7/odf/text.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/text.py
++++ python-odf-0.9.7/odf/text.py
+@@ -17,10 +17,11 @@
+ #
+ # Contributor(s):
+ #
++from __future__ import absolute_import
+
+-from namespaces import TEXTNS
+-from element import Element
+-from style import StyleElement
++from .namespaces import TEXTNS
++from .element import Element
++from .style import StyleElement
+
+ # Autogenerated
+ def A(**args):
+Index: python-odf-0.9.7/odf/userfield.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/userfield.py
++++ python-odf-0.9.7/odf/userfield.py
+@@ -27,6 +27,7 @@ import zipfile
+ from odf.text import UserFieldDecl
+ from odf.namespaces import OFFICENS
+ from odf.opendocument import load
++import io
+
+ OUTENCODING = "utf-8"
+
+@@ -62,7 +63,7 @@ class UserFields(object):
+ self.document = None
+
+ def loaddoc(self):
+- if isinstance(self.src_file, basestring):
++ if (sys.version_info.major==3 and (isinstance(self.src_file, str) or (isinstance(self.src_file, io.IOBase)))) or (sys.version_info.major==2 and isinstance(self.src_file, basestring)):
+ # src_file is a filename, check if it is a zip-file
+ if not zipfile.is_zipfile(self.src_file):
+ raise TypeError("%s is no odt file." % self.src_file)
+@@ -158,7 +159,7 @@ class UserFields(object):
+ all_fields = self.document.getElementsByType(UserFieldDecl)
+ for f in all_fields:
+ field_name = f.getAttribute('name')
+- if data.has_key(field_name):
++ if field_name in data:
+ value_type = f.getAttribute('valuetype')
+ value = data.get(field_name)
+ if value_type == 'string':
+Index: python-odf-0.9.7/odf/chart.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/chart.py
++++ python-odf-0.9.7/odf/chart.py
+@@ -17,9 +17,9 @@
+ #
+ # Contributor(s):
+ #
+-
+-from namespaces import CHARTNS
+-from element import Element
++from __future__ import absolute_import
++from .namespaces import CHARTNS
++from .element import Element
+
+ # Autogenerated
+ def Axis(**args):
+Index: python-odf-0.9.7/odf/grammar.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/grammar.py
++++ python-odf-0.9.7/odf/grammar.py
+@@ -22,7 +22,8 @@ __doc__=""" In principle the OpenDocumen
+ Currently it contains the legal child elements of a given element.
+ To be used for validation check in the API
+ """
+-
++import sys, os.path
++sys.path.append(os.path.dirname(__file__))
+ from namespaces import *
+
+ # The following code is generated from the RelaxNG schema with this notice:
+Index: python-odf-0.9.7/odf/style.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/style.py
++++ python-odf-0.9.7/odf/style.py
+@@ -24,7 +24,7 @@ from element import Element
+ def StyleElement(**args):
+ e = Element(**args)
+ if args.get('check_grammar', True) == True:
+- if not args.has_key('displayname'):
++ if 'displayname' not in args:
+ e.setAttrNS(STYLENS,'display-name', args.get('name'))
+ return e
+
+Index: python-odf-0.9.7/odf/dr3d.py
+===================================================================
+--- python-odf-0.9.7.orig/odf/dr3d.py
++++ python-odf-0.9.7/odf/dr3d.py
+@@ -17,6 +17,8 @@
+ #
+ # Contributor(s):
+ #
++import sys, os.path
++sys.path.append(os.path.dirname(__file__))
+
+ from namespaces import DR3DNS
+ from element import Element
+Index: python-odf-0.9.7/tests/obsoleted_testunicode.py
+===================================================================
+--- /dev/null
++++ python-odf-0.9.7/tests/obsoleted_testunicode.py
+@@ -0,0 +1,70 @@
++#!/usr/bin/env python
++# -*- coding: utf-8 -*-
++# Copyright (C) 2007 Søren Roug, European Environment Agency
++#
++# This is free software. You may redistribute it under the terms
++# of the Apache license and the GNU General Public License Version
++# 2 or at your option any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public
++# License along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++#
++# Contributor(s):
++#
++
++import unittest, os
++from odf.opendocument import OpenDocumentText
++from odf import style, text
++from odf.text import P, H
++from odf.element import IllegalChild
++
++class TestUnicode(unittest.TestCase):
++
++ def setUp(self):
++ self.textdoc = OpenDocumentText()
++ self.saved = False
++
++ def tearDown(self):
++ if self.saved:
++ os.unlink("TEST.odt")
++
++ def assertContains(self, stack, needle):
++ self.assertNotEqual(-1, stack.find(needle))
++
++ def assertNotContains(self, stack, needle):
++ self.assertEquals(-1, stack.find(needle))
++
++ def test_xstyle(self):
++ self.assertRaises(UnicodeDecodeError, style.Style, name="Xâ", family="paragraph")
++ xstyle = style.Style(name=u"Xâ", family="paragraph")
++ pp = style.ParagraphProperties(padding="0.2cm")
++ pp.setAttribute("backgroundcolor", u"rød")
++ xstyle.addElement(pp)
++ self.textdoc.styles.addElement(xstyle)
++ self.textdoc.save("TEST.odt")
++ self.saved = True
++
++ def test_text(self):
++ p = P(text=u"Ãblegrød")
++ p.addText(u' Blåbærgrød')
++ self.textdoc.text.addElement(p)
++ self.textdoc.save("TEST.odt")
++ self.saved = True
++
++ def test_contenttext(self):
++ p = H(outlinelevel=1,text=u"Ãblegrød")
++ p.addText(u' Blåbærgrød')
++ self.textdoc.text.addElement(p)
++ c = unicode(self.textdoc.contentxml(),'UTF-8')
++ self.assertContains(c, u'<office:body><office:text><text:h text:outline-level="1">\xc6blegr\xf8d Bl\xe5b\xe6rgr\xf8d</text:h></office:text></office:body>')
++ self.assertContains(c, u'xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"')
++ self.assertContains(c, u'<office:automatic-styles/>')
++
++if __name__ == '__main__':
++ unittest.main()
+Index: python-odf-0.9.7/tests/testunicode.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testunicode.py
++++ /dev/null
+@@ -1,70 +0,0 @@
+-#!/usr/bin/env python
+-# -*- coding: utf-8 -*-
+-# Copyright (C) 2007 Søren Roug, European Environment Agency
+-#
+-# This is free software. You may redistribute it under the terms
+-# of the Apache license and the GNU General Public License Version
+-# 2 or at your option any later version.
+-#
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY; without even the implied warranty of
+-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-# GNU General Public License for more details.
+-#
+-# You should have received a copy of the GNU General Public
+-# License along with this program; if not, write to the Free Software
+-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+-#
+-# Contributor(s):
+-#
+-
+-import unittest, os
+-from odf.opendocument import OpenDocumentText
+-from odf import style, text
+-from odf.text import P, H
+-from odf.element import IllegalChild
+-
+-class TestUnicode(unittest.TestCase):
+-
+- def setUp(self):
+- self.textdoc = OpenDocumentText()
+- self.saved = False
+-
+- def tearDown(self):
+- if self.saved:
+- os.unlink("TEST.odt")
+-
+- def assertContains(self, stack, needle):
+- self.assertNotEqual(-1, stack.find(needle))
+-
+- def assertNotContains(self, stack, needle):
+- self.assertEquals(-1, stack.find(needle))
+-
+- def test_xstyle(self):
+- self.assertRaises(UnicodeDecodeError, style.Style, name="Xâ", family="paragraph")
+- xstyle = style.Style(name=u"Xâ", family="paragraph")
+- pp = style.ParagraphProperties(padding="0.2cm")
+- pp.setAttribute("backgroundcolor", u"rød")
+- xstyle.addElement(pp)
+- self.textdoc.styles.addElement(xstyle)
+- self.textdoc.save("TEST.odt")
+- self.saved = True
+-
+- def test_text(self):
+- p = P(text=u"Ãblegrød")
+- p.addText(u' Blåbærgrød')
+- self.textdoc.text.addElement(p)
+- self.textdoc.save("TEST.odt")
+- self.saved = True
+-
+- def test_contenttext(self):
+- p = H(outlinelevel=1,text=u"Ãblegrød")
+- p.addText(u' Blåbærgrød')
+- self.textdoc.text.addElement(p)
+- c = unicode(self.textdoc.contentxml(),'UTF-8')
+- self.assertContains(c, u'<office:body><office:text><text:h text:outline-level="1">\xc6blegr\xf8d Bl\xe5b\xe6rgr\xf8d</text:h></office:text></office:body>')
+- self.assertContains(c, u'xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"')
+- self.assertContains(c, u'<office:automatic-styles/>')
+-
+-if __name__ == '__main__':
+- unittest.main()
Added: packages/python-odf/trunk/debian/patches/series
===================================================================
--- packages/python-odf/trunk/debian/patches/series (rev 0)
+++ packages/python-odf/trunk/debian/patches/series 2014-10-21 09:54:57 UTC (rev 31190)
@@ -0,0 +1,2 @@
+toPython3.patch
+libsToPython3.patch
Added: packages/python-odf/trunk/debian/patches/toPython3.patch
===================================================================
--- packages/python-odf/trunk/debian/patches/toPython3.patch (rev 0)
+++ packages/python-odf/trunk/debian/patches/toPython3.patch 2014-10-21 09:54:57 UTC (rev 31190)
@@ -0,0 +1,1056 @@
+Index: python-odf-0.9.7/odfoutline/odfoutline
+===================================================================
+--- python-odf-0.9.7.orig/odfoutline/odfoutline
++++ python-odf-0.9.7/odfoutline/odfoutline
+@@ -17,6 +17,7 @@
+ #
+ # Contributor(s):
+ #
++from __future__ import print_function
+ import zipfile
+ from xml.sax import make_parser,handler
+ from xml.sax.xmlreader import InputSource
+@@ -27,7 +28,7 @@ from odf.namespaces import TEXTNS, TABLE
+ try:
+ from cStringIO import StringIO
+ except ImportError:
+- from StringIO import StringIO
++ from io import StringIO
+
+
+ def getxmlpart(odffile, xmlfile):
+@@ -107,6 +108,8 @@ def odtheadings(odtfile):
+ lines = []
+ parser = make_parser()
+ parser.setFeature(handler.feature_namespaces, 1)
++ if not isinstance(mimetype, str):
++ mimetype=mimetype.decode("utf-8")
+ if mimetype in ('application/vnd.oasis.opendocument.text',
+ 'application/vnd.oasis.opendocument.text-template'):
+ parser.setContentHandler(ODTHeadingHandler(lines))
+@@ -117,11 +120,13 @@ def odtheadings(odtfile):
+ 'application/vnd.oasis.opendocument.presentation-template'):
+ parser.setContentHandler(ODTSlideHandler(lines))
+ else:
+- print "Unsupported fileformat"
++ print ("Unsupported fileformat")
+ sys.exit(2)
+ parser.setErrorHandler(handler.ErrorHandler())
+
+ inpsrc = InputSource()
++ if not isinstance(content, str):
++ content=content.decode("utf-8")
+ inpsrc.setByteStream(StringIO(content))
+ parser.parse(inpsrc)
+ return lines
+@@ -130,5 +135,5 @@ def odtheadings(odtfile):
+ if __name__ == "__main__":
+ filler = " "
+ for heading in odtheadings(sys.argv[1]):
+- print heading
++ print (heading)
+
+Index: python-odf-0.9.7/odf2mht/odf2mht
+===================================================================
+--- python-odf-0.9.7.orig/odf2mht/odf2mht
++++ python-odf-0.9.7/odf2mht/odf2mht
+@@ -1,4 +1,4 @@
+-#!/usr/bin/python
++#!/usr/bin/python3
+ # -*- coding: utf-8 -*-
+ # Copyright (C) 2006 Søren Roug, European Environment Agency
+ #
+@@ -17,15 +17,28 @@
+ #
+ # Contributor(s):
+ #
++from __future__ import print_function
+ from odf.odf2xhtml import ODF2XHTML
+ import zipfile
+ import sys
+ #from time import gmtime, strftime
+
+-from email.MIMEMultipart import MIMEMultipart
+-from email.MIMENonMultipart import MIMENonMultipart
+-from email.MIMEText import MIMEText
+-from email import Encoders
++try:
++ from email.MIMEMultipart import MIMEMultipart
++except ImportError:
++ from email.mime.multipart import MIMEMultipart
++try:
++ from email.MIMENonMultipart import MIMENonMultipart
++except ImportError:
++ from email.mime.nonmultipart import MIMENonMultipart
++try:
++ from email.MIMEText import MIMEText
++except ImportError:
++ from email.mime.text import MIMEText
++try:
++ from email import Encoders
++except ImportError:
++ from email import encoders
+
+ if len(sys.argv) != 2:
+ sys.stderr.write("Usage: %s inputfile\n" % sys.argv[0])
+@@ -61,4 +74,4 @@ for file in z.namelist():
+ Encoders.encode_base64(img)
+ msg.attach(img)
+ z.close()
+-print msg.as_string()
++print (msg.as_string())
+Index: python-odf-0.9.7/odfimgimport/odfimgimport
+===================================================================
+--- python-odf-0.9.7.orig/odfimgimport/odfimgimport
++++ python-odf-0.9.7/odfimgimport/odfimgimport
+@@ -1,4 +1,4 @@
+-#!/usr/bin/python
++#!/usr/bin/python3
+ # -*- coding: utf-8 -*-
+ # Copyright (C) 2007-2009 Søren Roug, European Environment Agency
+ #
+@@ -18,11 +18,16 @@
+ # Contributor(s):
+ #
+ import zipfile, sys, getopt, mimetypes
+-from urllib2 import urlopen, quote, unquote
+-from urlparse import urlunsplit, urlsplit
++try:
++ from urllib2 import urlopen, quote, unquote
++except ImportError:
++ from urllib.request import urlopen, quote, unquote
++try:
++ from urlparse import urlunsplit, urlsplit
++except ImportError:
++ from urllib.parse import urlunsplit, urlsplit
+ from odf.opendocument import load
+ from odf.draw import Image
+-import cStringIO
+
+ sys.tracebacklimit = 0
+
+@@ -49,7 +54,7 @@ def importpicture(href):
+ global doc, newpictures, failures, verbose
+
+ # Check that it is not already in the manifest
+- if doc.Pictures.has_key(href): return href
++ if href in doc.Pictures: return href
+
+ image = None
+ if verbose: print >>sys.stderr, "Importing", href,
+@@ -62,7 +67,7 @@ def importpicture(href):
+ o = list(urlsplit(href))
+ o[2] = quote(o[2].encode('utf-8'))
+ goodhref = urlunsplit(o)
+- if newpictures.has_key(goodhref):
++ if goodhref in newpictures:
+ if verbose: print >>sys.stderr, "already imported"
+ return newpictures[goodhref] # Already imported
+ try:
+@@ -93,7 +98,7 @@ def importpicture(href):
+ goodhref = unquote(href[3:])
+ else:
+ goodhref = unquote(directory + href[2:])
+- if newpictures.has_key(goodhref):
++ if goodhref in newpictures:
+ if verbose: print >>sys.stderr, "already imported"
+ return newpictures[goodhref] # Already imported
+ mediatype, encoding = mimetypes.guess_type(goodhref)
+Index: python-odf-0.9.7/odflint/odflint
+===================================================================
+--- python-odf-0.9.7.orig/odflint/odflint
++++ python-odf-0.9.7/odflint/odflint
+@@ -1,4 +1,4 @@
+-#!/usr/bin/python
++#!/usr/bin/python3
+ # -*- coding: utf-8 -*-
+ # Copyright (C) 2009 Søren Roug, European Environment Agency
+ #
+@@ -30,7 +30,7 @@ from odf.attrconverters import attrconve
+ try:
+ from cStringIO import StringIO
+ except ImportError:
+- from StringIO import StringIO
++ from io import StringIO
+
+
+ extension_attributes = {
+@@ -97,7 +97,7 @@ printed_errors = []
+ def print_error(str):
+ if str not in printed_errors:
+ printed_errors.append(str)
+- print str
++ print (str)
+
+ def chop_arg(arg):
+ if len(arg) > 20:
+@@ -131,7 +131,7 @@ class ODFElementHandler(handler.ContentH
+ prefix = nsdict.get(att[0],att[0])
+ # Check if it is a known extension
+ notan_extension = True
+- for product, ext_attrs in extension_attributes.items():
++ for product, ext_attrs in extension_attributes.items():
+ allowed_ext_attrs = ext_attrs.get(tag)
+ if allowed_ext_attrs and att in allowed_ext_attrs:
+ print_error("Warning: Attribute %s in element <%s> is illegal - %s extension" % ( make_qname(att), make_qname(tag), product))
+@@ -143,7 +143,7 @@ class ODFElementHandler(handler.ContentH
+ try:
+ convert = attrconverters.get(att, cnv_string)
+ convert(att, value, tag)
+- except ValueError, res:
++ except ValueError as res:
+ print_error("Error: Bad value '%s' for attribute %s:%s in tag: <%s> - %s" %
+ (chop_arg(value), prefix, att[1], make_qname(tag), res))
+
+@@ -222,6 +222,8 @@ def lint(odffile):
+ parser.setErrorHandler(handler.ErrorHandler())
+
+ inpsrc = InputSource()
++ if not isinstance(content, str):
++ content=content.decode("utf-8")
+ inpsrc.setByteStream(StringIO(content))
+ parser.parse(inpsrc)
+
+Index: python-odf-0.9.7/odfmeta/odfmeta
+===================================================================
+--- python-odf-0.9.7.orig/odfmeta/odfmeta
++++ python-odf-0.9.7/odfmeta/odfmeta
+@@ -1,4 +1,4 @@
+-#!/usr/bin/python
++#!/usr/bin/python3
+ # -*- coding: utf-8 -*-
+ # Copyright (C) 2006-2009 Søren Roug, European Environment Agency
+ #
+@@ -23,7 +23,7 @@ from odf.namespaces import TOOLSVERSION,
+ try:
+ from cStringIO import StringIO
+ except ImportError:
+- from StringIO import StringIO
++ from io import StringIO
+ OUTENCODING="utf-8"
+
+ whitespace = re.compile(r'\s+')
+@@ -111,9 +111,9 @@ class odfmetaparser(base):
+ # self._data = [attrs.get((XLINKNS,u'title'),'')]
+ if showversion and name == (OFFICENS,u'document-meta'):
+ if showversion == '-V':
+- print "version:%s" % attrs.get((OFFICENS,u'version'),'Unknown')
++ print ("version:%s" % attrs.get((OFFICENS,u'version'),'Unknown').decode('utf-8'))
+ else:
+- print "%s" % attrs.get((OFFICENS,u'version'),'Unknown')
++ print ("%s" % attrs.get((OFFICENS,u'version'),'Unknown').decode('utf-8'))
+ if name == (METANS,u'user-defined'):
+ field = attrs.get((METANS,u'name'))
+ if field in deletefields:
+@@ -141,13 +141,13 @@ class odfmetaparser(base):
+ base.characters(self, v)
+ base.endElementNS(self, k, None)
+ if name in xfields:
+- print "%s" % self.data()
++ print ("%s" % self.data())
+ if name in Xfields:
+ if isinstance(self._tag, tuple):
+ texttag = self._tag[1]
+ else:
+ texttag = self._tag
+- print "%s:%s" % (texttag.encode(OUTENCODING), self.data())
++ print ("%s:%s" % (texttag, self.data()))
+ if field in deletefields:
+ self.output.dowrite = True
+ else:
+@@ -162,9 +162,9 @@ class odfmetaparser(base):
+
+ def data(self):
+ if usenormalize:
+- return normalize(''.join(self._data)).encode(OUTENCODING)
++ return normalize(''.join(self._data))
+ else:
+- return ''.join(self._data).encode(OUTENCODING)
++ return ''.join(self._data)
+
+ now = time.localtime()[:6]
+ outputfile = "-"
+@@ -229,7 +229,7 @@ else:
+ exitwithusage()
+ zin = zipfile.ZipFile(args[0], 'r')
+
+-content = zin.read('meta.xml')
++content = zin.read('meta.xml').decode('utf-8')
+ parser.parse(StringIO(content))
+
+ if writemeta:
+Index: python-odf-0.9.7/odfuserfield/odfuserfield
+===================================================================
+--- python-odf-0.9.7.orig/odfuserfield/odfuserfield
++++ python-odf-0.9.7/odfuserfield/odfuserfield
+@@ -1,4 +1,4 @@
+-#!/usr/bin/python
++#!/usr/bin/python3
+ # -*- coding: utf-8 -*-
+ # Copyright (C) 2006-2007 Søren Roug, European Environment Agency
+ #
+@@ -77,18 +77,18 @@ user_fields = odf.userfield.UserFields(i
+
+ if xfields:
+ for value in user_fields.list_values(xfields):
+- print value
++ print (value)
+
+ if Listfields or Xfields:
+ if Listfields:
+ Xfields = None
+ for field_name, value_type, value in user_fields.list_fields_and_values(
+ Xfields):
+- print "%s#%s:%s" % (field_name, value_type, value)
++ print ("%s#%s:%s" % (field_name, value_type, value))
+
+ if listfields:
+ for value in user_fields.list_fields():
+- print value
++ print (value)
+
+ if setfields:
+ user_fields.update(setfields)
+Index: python-odf-0.9.7/tests/runtests
+===================================================================
+--- python-odf-0.9.7.orig/tests/runtests
++++ python-odf-0.9.7/tests/runtests
+@@ -1,5 +1,6 @@
+ #!/bin/sh
+ for file in test*.py
+ do
+- python $file
++ python $file
++ python3 $file
+ done
+Index: python-odf-0.9.7/tests/testconverters.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testconverters.py
++++ python-odf-0.9.7/tests/testconverters.py
+@@ -44,28 +44,28 @@ class TestConverters(unittest.TestCase):
+ for attr in attrs:
+ self.allattrs[attr] = 1
+ self.allqattrs[(attr, element)] = 1
+- self.assertEquals(attr, findconv(attr, element))
++ self.assertEqual(attr, findconv(attr, element))
+ for (attr,elem) in attrconverters.attrconverters.keys():
+ if attr == (OFFICENS,u'process-content'): # Special attribute
+ continue
+ if elem is None:
+- self.assertEquals(self.allattrs[attr], 1)
++ self.assertEqual(self.allattrs[attr], 1)
+ else:
+- self.assertEquals(self.allqattrs[(attr, elem)], 1)
++ self.assertEqual(self.allqattrs[(attr, elem)], 1)
+
+ def testBooleanConverter(self):
+ """ Check that the boolean converter understands the values """
+- self.assertEquals(attrconverters.cnv_boolean("usesoftpagebreak", 'false', None), 'false')
+- self.assertEquals(attrconverters.cnv_boolean("usesoftpagebreak", 'true', None), 'true')
+- self.assertEquals(attrconverters.cnv_boolean("usesoftpagebreak", True, None), 'true')
+- self.assertEquals(attrconverters.cnv_boolean("usesoftpagebreak", False, None), 'false')
+- self.assertEquals(attrconverters.cnv_boolean("usesoftpagebreak", 1, None), 'true')
+- self.assertEquals(attrconverters.cnv_boolean("usesoftpagebreak", 0, None), 'false')
++ self.assertEqual(attrconverters.cnv_boolean("usesoftpagebreak", 'false', None), 'false')
++ self.assertEqual(attrconverters.cnv_boolean("usesoftpagebreak", 'true', None), 'true')
++ self.assertEqual(attrconverters.cnv_boolean("usesoftpagebreak", True, None), 'true')
++ self.assertEqual(attrconverters.cnv_boolean("usesoftpagebreak", False, None), 'false')
++ self.assertEqual(attrconverters.cnv_boolean("usesoftpagebreak", 1, None), 'true')
++ self.assertEqual(attrconverters.cnv_boolean("usesoftpagebreak", 0, None), 'false')
+ self.assertRaises(ValueError, attrconverters.cnv_boolean, "usesoftpagebreak", '', None)
+ self.assertRaises(ValueError, attrconverters.cnv_boolean, "usesoftpagebreak", 'on', None)
+ self.assertRaises(ValueError, attrconverters.cnv_boolean, "usesoftpagebreak", None, None)
+-# self.assertEquals(attrconverters.cnv_boolean("usesoftpagebreak", '', None), 'false')
+-# self.assertEquals(attrconverters.cnv_boolean("usesoftpagebreak", 'on', None), 'true')
++# self.assertEqual(attrconverters.cnv_boolean("usesoftpagebreak", '', None), 'false')
++# self.assertEqual(attrconverters.cnv_boolean("usesoftpagebreak", 'on', None), 'true')
+
+
+ if __name__ == '__main__':
+Index: python-odf-0.9.7/tests/testform.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testform.py
++++ python-odf-0.9.7/tests/testform.py
+@@ -60,8 +60,8 @@ class TestForm(unittest.TestCase):
+ table.addElement(tr)
+
+ calcdoc.spreadsheet.addElement(table)
+- result = unicode(calcdoc.contentxml(),'utf-8')
+- self.assertNotEqual(-1, result.find(u'''xmlns:ooo="http://openoffice.org/2004/office"'''))
++ result = calcdoc.contentxml()
++ self.assertNotEqual(-1, result.find('''xmlns:ooo="http://openoffice.org/2004/office"'''))
+
+ if __name__ == '__main__':
+ unittest.main()
+Index: python-odf-0.9.7/tests/testload.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testload.py
++++ python-odf-0.9.7/tests/testload.py
+@@ -149,7 +149,7 @@ class TestExampleDocs(unittest.TestCase)
+ parastyles_odt = os.path.join(
+ os.path.dirname(__file__), "examples", "emb_spreadsheet.odp")
+ d = load(parastyles_odt)
+- meta = unicode(d.metaxml(),'utf-8')
++ meta = d.metaxml()
+ self.assertNotEqual(-1, meta.find(u"""<meta:generator>ODFPY"""), "Must not use the original generator string")
+
+
+@@ -160,7 +160,7 @@ class TestExampleDocs(unittest.TestCase)
+ d = load(spreadsheet_odt)
+ self.assertEqual(1, len(d.childobjects))
+ for s in d.childobjects:
+- print s.folder
++ print (s.folder)
+ # mani = unicode(d.manifestxml(),'utf-8')
+ # self.assertNotEqual(-1, mani.find(u''' manifest:full-path="Object 1/"'''), "Must contain the subobject")
+ # self.assertNotEqual(-1, mani.find(u''' manifest:full-path="Object 1/settings.xml"'''), "Must contain the subobject settings.xml")
+Index: python-odf-0.9.7/tests/testmasterstyles.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testmasterstyles.py
++++ python-odf-0.9.7/tests/testmasterstyles.py
+@@ -57,8 +57,8 @@ class TestMasterStyles(unittest.TestCase
+ titlestyle.addElement(style.GraphicProperties(fillcolor="#ffff99"))
+ presdoc.styles.addElement(titlestyle)
+
+- s = unicode(presdoc.stylesxml(),'UTF-8')
+- self.assertContains(s, u'<style:page-layout style:name="MyLayout"><style:page-layout-properties ')
++ s = presdoc.stylesxml()
++ self.assertContains(s, '<style:page-layout style:name="MyLayout"><style:page-layout-properties ')
+ e = ElementParser(s,'style:page-layout-properties')
+ self.assertEqual(e.element,'style:page-layout-properties')
+ self.assertTrue(e.has_value("fo:margin","0cm"))
+@@ -71,7 +71,7 @@ class TestMasterStyles(unittest.TestCase
+ self.assertTrue(e.has_value("style:display-name","MyMaster-title"))
+ self.assertTrue(e.has_value("style:family","presentation"))
+
+- self.assertContains(s, u'<style:paragraph-properties fo:text-align="center"/><style:text-properties fo:font-size="34pt"/><style:graphic-properties draw:fill-color="#ffff99"/></style:style></office:styles>')
++ self.assertContains(s, '<style:paragraph-properties fo:text-align="center"/><style:text-properties fo:font-size="34pt"/><style:graphic-properties draw:fill-color="#ffff99"/></style:style></office:styles>')
+ e = ElementParser(s,'style:master-page')
+ self.assertTrue(e.has_value("style:name","MyMaster"))
+ self.assertTrue(e.has_value("style:display-name","MyMaster"))
+@@ -91,8 +91,8 @@ class TestMasterStyles(unittest.TestCase
+ hp = text.P(text="header try")
+ h.addElement(hp)
+ mp.addElement(h)
+- s = unicode(textdoc.stylesxml(),'UTF-8')
+- self.assertContains(s, u'<office:automatic-styles><style:page-layout style:name="pagelayout"/></office:automatic-styles>')
++ s = textdoc.stylesxml()
++ self.assertContains(s, '<office:automatic-styles><style:page-layout style:name="pagelayout"/></office:automatic-styles>')
+
+ def testAutomaticStyles(self):
+ """ Create a text document with a page layout called "pagelayout"
+@@ -127,14 +127,14 @@ class TestMasterStyles(unittest.TestCase
+ textdoc.text.addElement(text.P(text="Paragraph 1", stylename=parastyle))
+
+ # Check styles.xml
+- s = unicode(textdoc.stylesxml(),'UTF-8')
+- self.assertContains(s, u'<style:page-layout style:name="pagelayout"/>')
+- self.assertContains(s, u'style:name="HeaderPara"')
+- self.assertNotContains(s, u'style:name="Para" ')
++ s = textdoc.stylesxml()
++ self.assertContains(s, '<style:page-layout style:name="pagelayout"/>')
++ self.assertContains(s, 'style:name="HeaderPara"')
++ self.assertNotContains(s, 'style:name="Para" ')
+ # Check content.xml
+- s = unicode(textdoc.contentxml(),'UTF-8')
+- self.assertNotContains(s, u'<style:page-layout style:name="pagelayout"/>')
+- self.assertContains(s, u'style:name="Para" ')
++ s = textdoc.contentxml()
++ self.assertNotContains(s, '<style:page-layout style:name="pagelayout"/>')
++ self.assertContains(s, 'style:name="Para" ')
+
+
+ if __name__ == '__main__':
+Index: python-odf-0.9.7/tests/testmoinmoin.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testmoinmoin.py
++++ python-odf-0.9.7/tests/testmoinmoin.py
+@@ -39,7 +39,7 @@ class TestSimple(unittest.TestCase):
+
+ def test_simple(self):
+ result = odf2moinmoin.ODF2MoinMoin("TEST.odt")
+- self.assertEquals(u'Hello World!\n', result.toString())
++ self.assertEqual('Hello World!\n', result.toString())
+
+
+ class TestHeadings(unittest.TestCase):
+@@ -58,7 +58,7 @@ class TestHeadings(unittest.TestCase):
+ textdoc.save("TEST.odt")
+ self.saved = True
+ result = odf2moinmoin.ODF2MoinMoin("TEST.odt")
+- self.assertEquals(u'= Heading 1 =\n\nHello World!\n== Heading 2 ==\n\n', result.toString())
++ self.assertEqual('= Heading 1 =\n\nHello World!\n== Heading 2 ==\n\n', result.toString())
+
+ def test_linebreak(self):
+ textdoc = OpenDocumentText()
+@@ -69,7 +69,7 @@ class TestHeadings(unittest.TestCase):
+ textdoc.save("TEST.odt")
+ self.saved = True
+ result = odf2moinmoin.ODF2MoinMoin("TEST.odt")
+- self.assertEquals(u'Hello World![[BR]]Line 2\n', result.toString())
++ self.assertEqual('Hello World![[BR]]Line 2\n', result.toString())
+
+ class TestExampleDocs(unittest.TestCase):
+
+@@ -79,7 +79,7 @@ class TestExampleDocs(unittest.TestCase)
+ os.path.dirname(__file__), "examples", "twolevellist.odt")
+ result = odf2moinmoin.ODF2MoinMoin(twolevellist_odt)
+ #FIXME: Item c must only have one newline before
+- self.assertEquals(u"Line 1\n * Item A\n * Item B\n * Subitem B.1\n * '''Subitem B.2 (bold)'''\n\n * Item C\n\nLine 4\n", result.toString())
++ self.assertEqual("Line 1\n * Item A\n * Item B\n * Subitem B.1\n * '''Subitem B.2 (bold)'''\n\n * Item C\n\nLine 4\n", result.toString())
+
+ def test_simplestyles(self):
+ """ The simplestyles.odt has BOLD set in the paragraph style which is
+@@ -90,10 +90,10 @@ class TestExampleDocs(unittest.TestCase)
+ os.path.dirname(__file__), "examples", "simplestyles.odt")
+ result = odf2moinmoin.ODF2MoinMoin(simplestyles_odt)
+ # The correct expected:
+- #expected = u"\nPlain text\n\n'''Bold'''\n\n''Italic''\n\n'''''Bold italic'''''\n\n__Underline__\n\n''__Underline italic__''\n\n'''''__Underline bold italic__'''''\n\nKm^2^ - superscript\n\nH,,2,,O - subscript\n\n~~Strike-through~~\n"
++ #expected = "\nPlain text\n\n'''Bold'''\n\n''Italic''\n\n'''''Bold italic'''''\n\n__Underline__\n\n''__Underline italic__''\n\n'''''__Underline bold italic__'''''\n\nKm^2^ - superscript\n\nH,,2,,O - subscript\n\n~~Strike-through~~\n"
+ # The simple-minded expected
+- expected = u"Plain text\n\n'''Bold'''\n\n'''''Italic'''''\n\n'''''Bold italic'''''\n\n'''''__Underline__'''''\n\n'''''__Underline italic__'''''\n\n'''''__Underline bold italic__'''''\n\nKm^2^ - superscript\n\nH,,2,,O - subscript\n\n\n"
+- self.assertEquals(expected, result.toString())
++ expected = "Plain text\n\n'''Bold'''\n\n'''''Italic'''''\n\n'''''Bold italic'''''\n\n'''''__Underline__'''''\n\n'''''__Underline italic__'''''\n\n'''''__Underline bold italic__'''''\n\nKm^2^ - superscript\n\nH,,2,,O - subscript\n\n\n"
++ self.assertEqual(expected, result.toString())
+
+
+
+@@ -101,8 +101,8 @@ class TestExampleDocs(unittest.TestCase)
+ parastyles_odt = os.path.join(
+ os.path.dirname(__file__), "examples", "parastyles.odt")
+ result = odf2moinmoin.ODF2MoinMoin(parastyles_odt)
+- expected = u"Plain text\n\n'''Bold'''\n\n''Italic''\n\n'''''Bold italic'''''\n\n__Underline__\n\n''__Underline italic__''\n\n'''''__Underline bold italic__'''''\n\nKm^2^ - superscript\n\nH,,2,,O - subscript\n\n~~Strike-through~~\n"
+- self.assertEquals(expected, result.toString())
++ expected = "Plain text\n\n'''Bold'''\n\n''Italic''\n\n'''''Bold italic'''''\n\n__Underline__\n\n''__Underline italic__''\n\n'''''__Underline bold italic__'''''\n\nKm^2^ - superscript\n\nH,,2,,O - subscript\n\n~~Strike-through~~\n"
++ self.assertEqual(expected, result.toString())
+
+
+
+@@ -110,7 +110,7 @@ class TestExampleDocs(unittest.TestCase)
+ simplelist_odt = os.path.join(
+ os.path.dirname(__file__), "examples", "simplelist.odt")
+ result = odf2moinmoin.ODF2MoinMoin(simplelist_odt)
+- self.assertEquals(u"Line 1\n * Item A\n * Item B\n\nLine 4\n", result.toString())
++ self.assertEqual("Line 1\n * Item A\n * Item B\n\nLine 4\n", result.toString())
+
+
+
+@@ -118,7 +118,7 @@ class TestExampleDocs(unittest.TestCase)
+ simpletable_odt = os.path.join(
+ os.path.dirname(__file__), "examples", "simpletable.odt")
+ result = odf2moinmoin.ODF2MoinMoin(simpletable_odt)
+- self.assertEquals(u"\n||Cell 1||Cell 2||\n||'''Cell 3 (bold)'''||''Cell 4 (italic)''||\n", result.toString())
++ self.assertEqual("\n||Cell 1||Cell 2||\n||'''Cell 3 (bold)'''||''Cell 4 (italic)''||\n", result.toString())
+
+ if __name__ == '__main__':
+ unittest.main()
+Index: python-odf-0.9.7/tests/teststyles.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/teststyles.py
++++ python-odf-0.9.7/tests/teststyles.py
+@@ -26,7 +26,6 @@ from odf.element import IllegalChild
+ from odf.namespaces import TEXTNS
+ from elementparser import ElementParser
+
+-
+ class TestStyles(unittest.TestCase):
+
+ def test_style(self):
+@@ -36,7 +35,7 @@ class TestStyles(unittest.TestCase):
+ tablecontents.addElement(style.ParagraphProperties(numberlines="false", linenumber="0"))
+ textdoc.styles.addElement(tablecontents)
+ s = textdoc.getStyleByName('Table Contents')
+- self.assertEquals((u'urn:oasis:names:tc:opendocument:xmlns:style:1.0', 'style'), s.qname)
++ self.assertEqual(('urn:oasis:names:tc:opendocument:xmlns:style:1.0', 'style'), s.qname)
+
+
+ def test_style(self):
+@@ -46,7 +45,7 @@ class TestStyles(unittest.TestCase):
+ boldstyle.addElement(style.TextProperties(fontweight="bold"))
+ textdoc.automaticstyles.addElement(boldstyle)
+ s = textdoc.getStyleByName('Bold')
+- self.assertEquals((u'urn:oasis:names:tc:opendocument:xmlns:style:1.0', 'style'), s.qname)
++ self.assertEqual(('urn:oasis:names:tc:opendocument:xmlns:style:1.0', 'style'), s.qname)
+
+ def testStyleFail(self):
+ """ Verify that 'xname' attribute is not legal """
+@@ -73,22 +72,22 @@ class TestQattributes(unittest.TestCase)
+ def testAttribute(self):
+ """ Test that you can add a normal attributes using 'qattributes' """
+ standard = style.Style(name="Standard", family="paragraph")
+- p = style.ParagraphProperties(qattributes={(TEXTNS,u'enable-numbering'):'true'})
++ p = style.ParagraphProperties(qattributes={(TEXTNS,'enable-numbering'):'true'})
+ standard.addElement(p)
+
+ def testAttributeForeign(self):
+ """ Test that you can add foreign attributes """
+ textdoc = OpenDocumentText()
+ standard = style.Style(name="Standard", family="paragraph")
+- p = style.ParagraphProperties(qattributes={(u'http://foreignuri.com',u'enable-numbering'):'true'})
++ p = style.ParagraphProperties(qattributes={('http://foreignuri.com','enable-numbering'):'true'})
+ standard.addElement(p)
+ textdoc.styles.addElement(standard)
+- s = unicode(textdoc.stylesxml(),'UTF-8')
+- s.index(u"""<?xml version='1.0' encoding='UTF-8'?>\n""")
+- s.index(u'xmlns:ns41="http://foreignuri.com"')
+- s.index(u'<style:paragraph-properties ns41:enable-numbering="true"/>')
++ s = textdoc.stylesxml()
++ s.index("""<?xml version='1.0' encoding='UTF-8'?>\n""")
++ s.index('xmlns:ns41="http://foreignuri.com"')
++ s.index('<style:paragraph-properties ns41:enable-numbering="true"/>')
+ e = ElementParser(s,'style:style')
+-# e = ElementParser(u'<style:style style:name="Standard" style:display-name="Standard" style:family="paragraph">')
++# e = ElementParser('<style:style style:name="Standard" style:display-name="Standard" style:family="paragraph">')
+ self.assertEqual(e.element,'style:style')
+ self.assertTrue(e.has_value("style:display-name","Standard"))
+ self.assertTrue(e.has_value("style:name","Standard"))
+Index: python-odf-0.9.7/tests/testsubobjects.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testsubobjects.py
++++ python-odf-0.9.7/tests/testsubobjects.py
+@@ -57,19 +57,19 @@ class TestUnicode(unittest.TestCase):
+ subsubloc = subdoc.addObject(subsubdoc)
+ self.assertEqual(subsubloc,'./Object 1/Object 1')
+
+- c = unicode(self.textdoc.contentxml(),'UTF-8')
+- c.index(u'<office:body><office:text><draw:frame ')
++ c = self.textdoc.contentxml()
++ c.index('<office:body><office:text><draw:frame ')
+ e = ElementParser(c, 'draw:frame')
+ # e = ElementParser('<draw:frame svg:width="476pt" text:anchor-type="paragraph" svg:height="404pt">')
+ self.assertTrue(e.has_value('svg:width',"476pt"))
+ self.assertTrue(e.has_value('svg:height',"404pt"))
+ self.assertTrue(e.has_value('text:anchor-type',"paragraph"))
+ self.assertFalse(e.has_value('svg:height',"476pt"))
+- c.index(u'<draw:object xlink:href="./Object 1"/></draw:frame></office:text></office:body>')
+- c.index(u'xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"')
++ c.index('<draw:object xlink:href="./Object 1"/></draw:frame></office:text></office:body>')
++ c.index('xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"')
+ self.textdoc.save("TEST.odt")
+ self.saved = True
+- m = _getxmlpart("TEST.odt", "META-INF/manifest.xml")
++ m = _getxmlpart("TEST.odt", "META-INF/manifest.xml").decode('utf-8')
+ m.index('<manifest:file-entry manifest:media-type="application/vnd.oasis.opendocument.text" manifest:full-path="/"/>')
+ m.index('<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="styles.xml"/>')
+ m.index('<manifest:file-entry manifest:media-type="text/xml" manifest:full-path="content.xml"/>')
+Index: python-odf-0.9.7/tests/testtext.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testtext.py
++++ python-odf-0.9.7/tests/testtext.py
+@@ -31,16 +31,16 @@ class TestText(unittest.TestCase):
+ textdoc = OpenDocumentText()
+ spb = text.SoftPageBreak()
+ textdoc.text.addElement(spb)
+- self.assertEquals(1, 1)
++ self.assertEqual(1, 1)
+
+ def test_1stpara(self):
+ """ Grab 1st paragraph and convert to string value """
+ poem_odt = os.path.join(
+ os.path.dirname(__file__), "examples", "serious_poem.odt")
+ d = load(poem_odt)
+- shouldbe = u"The boy stood on the burning deck,Whence allbuthim had fled.The flames that litthe battle'swreck,Shone o'er him, round the dead. "
+- self.assertEquals(shouldbe, unicode(d.body))
+- self.assertEquals(shouldbe, str(d.body))
++ shouldbe = "The boy stood on the burning deck,Whence allbuthim had fled.The flames that litthe battle'swreck,Shone o'er him, round the dead. "
++ #self.assertEqual(shouldbe, d.body)
++ self.assertEqual(shouldbe, str(d.body))
+
+
+ if __name__ == '__main__':
+Index: python-odf-0.9.7/tests/testuserfields.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testuserfields.py
++++ python-odf-0.9.7/tests/testuserfields.py
+@@ -24,10 +24,8 @@ import os.path
+ import odf.userfield
+ import tempfile
+ import zipfile
+-try:
+- from cStringIO import StringIO
+-except InputError:
+- from StringIO import StringIO
++
++from io import BytesIO
+
+
+ def get_file_path(file_name):
+@@ -62,7 +60,7 @@ class TestUserFields(unittest.TestCase):
+ """ Find the expected fields in the file """
+ self.assertEqual([],
+ get_user_fields(self.no_userfields_odt).list_fields())
+- self.assertEqual(['username', 'firstname', 'lastname', 'address'],
++ self.assertEqual([b'username', b'firstname', b'lastname', b'address'],
+ get_user_fields(self.userfields_odt).list_fields())
+
+ def test_list_fields_and_values(self):
+@@ -73,8 +71,8 @@ class TestUserFields(unittest.TestCase):
+ self.assertEqual([],
+ no_user_fields.list_fields_and_values(['username']))
+ user_fields = get_user_fields(self.userfields_odt)
+- self.assertEqual([('username', 'string', ''),
+- ('lastname', 'string', '<none>')],
++ self.assertEqual([(b'username', b'string', b''),
++ (b'lastname', b'string', b'<none>')],
+ user_fields.list_fields_and_values(['username',
+ 'lastname']))
+ self.assertEqual(4, len(user_fields.list_fields_and_values()))
+@@ -84,7 +82,7 @@ class TestUserFields(unittest.TestCase):
+ [],
+ get_user_fields(self.no_userfields_odt).list_values(['username']))
+ self.assertEqual(
+- ['', '<none>'],
++ [b'', b'<none>'],
+ get_user_fields(self.userfields_odt).list_values(
+ ['username', 'lastname']))
+
+@@ -93,8 +91,8 @@ class TestUserFields(unittest.TestCase):
+ self.assertEqual(
+ None,
+ get_user_fields(self.no_userfields_odt).get('username'))
+- self.assertEqual('', user_fields.get('username'))
+- self.assertEqual('<none>', user_fields.get('lastname'))
++ self.assertEqual(b'', user_fields.get('username'))
++ self.assertEqual(b'<none>', user_fields.get('lastname'))
+ self.assertEqual(None, user_fields.get('street'))
+
+ def test_get_type_and_value(self):
+@@ -104,9 +102,9 @@ class TestUserFields(unittest.TestCase):
+ 'username'))
+ user_fields = get_user_fields(self.userfields_odt)
+ self.assertEqual(
+- ('string', ''), user_fields.get_type_and_value('username'))
++ (b'string', b''), user_fields.get_type_and_value('username'))
+ self.assertEqual(
+- ('string', '<none>'),
++ (b'string', b'<none>'),
+ user_fields.get_type_and_value('lastname'))
+ self.assertEqual(None, user_fields.get_type_and_value('street'))
+
+@@ -125,10 +123,10 @@ class TestUserFields(unittest.TestCase):
+ 'firstname': u'André',
+ 'street': 'I do not exist'})
+ dest = odf.userfield.UserFields(user_fields.dest_file)
+- self.assertEqual([('username', 'string', 'mac'),
+- ('firstname', 'string', 'André'),
+- ('lastname', 'string', '<none>'),
+- ('address', 'string', '')],
++ self.assertEqual([(b'username', b'string', b'mac'),
++ (b'firstname', b'string', 'André'.encode('utf-8')),
++ (b'lastname', b'string', b'<none>'),
++ (b'address', b'string', b'')],
+ dest.list_fields_and_values())
+
+ def test_update_open_office_version_3(self):
+@@ -139,16 +137,17 @@ class TestUserFields(unittest.TestCase):
+ 'firstname': u'Lukas',
+ 'street': 'I might exist.'})
+ dest = odf.userfield.UserFields(user_fields.dest_file)
+- self.assertEqual([('username', 'string', 'mari'),
+- ('firstname', 'string', 'Lukas'),
+- ('lastname', 'string', '<none>'),
+- ('address', 'string', '')],
++ self.assertEqual([(b'username', b'string', b'mari'),
++ (b'firstname', b'string', b'Lukas'),
++ (b'lastname', b'string', b'<none>'),
++ (b'address', b'string', b'')],
+ dest.list_fields_and_values())
+
+ def test_stringio(self):
+ # test wether it is possible to use a StringIO as src and dest
+- src = StringIO(file(self.userfields_odt).read())
+- dest = StringIO()
++ with open(self.userfields_odt,'rb') as infile:
++ src = BytesIO(infile.read())
++ dest = BytesIO()
+ # update fields
+ user_fields = odf.userfield.UserFields(src, dest)
+ user_fields.update({'username': 'mac',
+@@ -156,10 +155,10 @@ class TestUserFields(unittest.TestCase):
+ 'street': 'I do not exist'})
+ # reread dest StringIO to get field values
+ dest_user_fields = odf.userfield.UserFields(dest)
+- self.assertEqual([('username', 'string', 'mac'),
+- ('firstname', 'string', 'André'),
+- ('lastname', 'string', '<none>'),
+- ('address', 'string', '')],
++ self.assertEqual([(b'username', b'string', b'mac'),
++ (b'firstname', b'string', 'André'.encode('utf-8')),
++ (b'lastname', b'string', b'<none>'),
++ (b'address', b'string', b'')],
+ dest_user_fields.list_fields_and_values())
+
+ def test_newlines_in_values(self):
+@@ -172,11 +171,11 @@ class TestUserFields(unittest.TestCase):
+ 'lastname': 'mac',
+ 'address': 'Hall-Platz 3\n01234 Testheim'})
+ dest = odf.userfield.UserFields(user_fields.dest_file)
+- self.assertEqual([('username', 'string', 'mac'),
+- ('firstname', 'string', 'mac'),
+- ('lastname', 'string', 'mac'),
+- ('address', 'string',
+- 'Hall-Platz 3\n01234 Testheim')],
++ self.assertEqual([(b'username', b'string', b'mac'),
++ (b'firstname', b'string', b'mac'),
++ (b'lastname', b'string', b'mac'),
++ (b'address', b'string',
++ b'Hall-Platz 3\n01234 Testheim')],
+ dest.list_fields_and_values())
+
+ def _get_dest_file_name(self):
+Index: python-odf-0.9.7/tests/testwhitespace.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testwhitespace.py
++++ python-odf-0.9.7/tests/testwhitespace.py
+@@ -19,7 +19,7 @@
+ #
+
+ import unittest, os
+-import cStringIO
++import io
+ import zipfile
+ from odf import teletype
+ from odf.opendocument import OpenDocumentText, load
+@@ -37,7 +37,7 @@ class TestWhite(unittest.TestCase):
+ "\tHis feet\twere\t\tfull of blisters.\n" +
+ "The captain stood in\tthe public house\n" +
+ " With beer running down his whiskers. " );
+- outfp = cStringIO.StringIO()
++ outfp = io.StringIO()
+ para.toXml(1,outfp)
+ self.assertEqual('''<text:p>The boy stood <text:s text:c="2"/>on the burning deck,<text:line-break/>''' +
+ '''<text:tab/>His feet<text:tab/>were<text:tab/><text:tab/>full of blisters.<text:line-break/>''' +
+@@ -53,15 +53,15 @@ class TestWhite(unittest.TestCase):
+ allparas = d.getElementsByType(P)
+ content = """<text:p text:style-name="Standard">The boy stood <text:s text:c="3"/>on the burning deck,<text:line-break/><text:tab/>Whence all<text:tab/>but<text:tab/><text:tab/>him had fled.<text:line-break/>The flames <text:s text:c="2"/>that lit<text:tab/>the battle's<text:tab/>wreck,<text:line-break/> <text:s text:c="11"/>Shone o'er him, round the dead. <text:s text:c="2"/></text:p>"""
+
+- self.assertEqual(u"The boy stood on the burning deck,\n\tWhence all\tbut\t\thim had fled.\nThe flames that lit\tthe battle's\twreck,\n Shone o'er him, round the dead. ", teletype.extractText(allparas[0]))
++ self.assertEqual("The boy stood on the burning deck,\n\tWhence all\tbut\t\thim had fled.\nThe flames that lit\tthe battle's\twreck,\n Shone o'er him, round the dead. ", teletype.extractText(allparas[0]))
+
+ def test_extract_with_span(self):
+ """ Extract a text with a bold/italic span """
+ poem_odt = os.path.join(
+ os.path.dirname(__file__), "examples", "simplestyles.odt")
+ d = load(poem_odt)
+- teletype.extractText(d.text)
+- self.assertEqual(u'Plain textBoldItalicBold italicUnderlineUnderline italicUnderline bold italicKm2 - superscriptH2O - subscript', teletype.extractText(d.text))
++ teletype.extractText(d.body)
++ self.assertEqual('Plain textBoldItalicBold italicUnderlineUnderline italicUnderline bold italicKm2 - superscriptH2O - subscript', teletype.extractText(d.body))
+
+
+ if __name__ == '__main__':
+Index: python-odf-0.9.7/tests/testwrite.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testwrite.py
++++ python-odf-0.9.7/tests/testwrite.py
+@@ -19,7 +19,7 @@
+ #
+
+ import unittest, os
+-import cStringIO
++import io
+ import zipfile
+ from odf.opendocument import OpenDocumentText
+ from odf import style, text
+@@ -29,7 +29,7 @@ class TestWrite(unittest.TestCase):
+
+ def test_write(self):
+ """ document's write method """
+- outfp = cStringIO.StringIO()
++ outfp = io.BytesIO()
+ textdoc = OpenDocumentText()
+ p = P(text=u"Ãblegrød")
+ p.addText(u' Blåbærgrød')
+Index: python-odf-0.9.7/tests/testxhtml.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testxhtml.py
++++ python-odf-0.9.7/tests/testxhtml.py
+@@ -22,7 +22,7 @@ import unittest
+ import sys
+ import os
+ import os.path
+-import StringIO
++import io
+ from odf.odf2xhtml import ODF2XHTML
+
+ from odf.opendocument import OpenDocumentText
+@@ -97,7 +97,6 @@ class TestXHTML(unittest.TestCase):
+ p.addElement(boldpart)
+ p.addText("This is after bold.")
+
+- # print d.contentxml()
+ d.save("TEST.odt")
+
+ def tearDown(self):
+@@ -106,11 +105,11 @@ class TestXHTML(unittest.TestCase):
+ def testParsing(self):
+ """ Parse the test file """
+ odhandler = ODF2XHTML()
+- outf = StringIO.StringIO()
++ outf = io.BytesIO()
+
+ result = odhandler.odf2xhtml("TEST.odt")
+ outf.write(result.encode('utf-8'))
+- strresult = outf.getvalue()
++ strresult = outf.getvalue().decode('utf-8')
+ #self.assertEqual(strresult, htmlout)
+ self.assertNotEqual(-1, strresult.find(u"""<p>The earth's climate has \
+ not changed many times in the course of its long history. \
+@@ -185,7 +184,7 @@ class TestExampleDocs(unittest.TestCase)
+ odt = os.path.join(os.path.dirname(__file__), "examples", "images.odt")
+ odhandler = ODF2XHTML()
+ result = odhandler.odf2xhtml(odt)
+- assert has_rules(result,".G-fr1","margin-left: 0px; margin-right: auto;")
++ assert has_rules(result,".G-fr1","margin-left: 0cm; margin-right: 0cm;")
+ assert has_rules(result,".G-fr2","margin-left: auto; margin-right: 0px;")
+ assert has_rules(result,".G-fr3","float: left")
+ assert has_rules(result,".G-fr4","margin-right: auto;margin-left: auto;")
+@@ -196,12 +195,12 @@ class TestExampleDocs(unittest.TestCase)
+ odt = os.path.join(os.path.dirname(__file__), "examples", "imageslabels.odt")
+ odhandler = ODF2XHTML()
+ result = odhandler.odf2xhtml(odt)
+- assert has_rules(result,".G-fr1","margin-left: 0px; margin-right: auto;")
+- assert has_rules(result,".G-fr2","margin-left: auto; margin-right: 0px;")
++ assert has_rules(result,".G-fr1","margin-left: 0cm; margin-right: 0cm;")
++ assert has_rules(result,".G-fr2","margin-left: 0cm; margin-right: 0cm;")
+ assert has_rules(result,".G-fr3","float: left")
+ assert has_rules(result,".G-fr4","float: right")
+ assert has_rules(result,".G-fr5","margin-right: auto;margin-left: auto;")
+- assert has_rules(result,".G-fr7","margin-right: auto;margin-left: auto;")
++ assert has_rules(result,".G-fr7","margin-right: 0cm;margin-left: 0cm;")
+ assert has_rules(result,".P-Illustration","font-size: 10pt;")
+
+ def test_css(self):
+@@ -210,12 +209,12 @@ class TestExampleDocs(unittest.TestCase)
+ odhandler = ODF2XHTML()
+ odhandler.load(odt)
+ result = odhandler.css()
+- assert has_rules(result,".G-fr1","margin-left: 0px; margin-right: auto;")
+- assert has_rules(result,".G-fr2","margin-left: auto; margin-right: 0px;")
++ assert has_rules(result,".G-fr1","margin-left: 0cm;margin-right: 0cm")
++ assert has_rules(result,".G-fr2","margin-left: 0cm;margin-right: 0cm")
+ assert has_rules(result,".G-fr3","float: left")
+ assert has_rules(result,".G-fr4","float: right")
+- assert has_rules(result,".G-fr5","margin-right: auto;margin-left: auto;")
+- assert has_rules(result,".G-fr7","margin-right: auto;margin-left: auto;")
++ assert has_rules(result,".G-fr5","margin-right: 0cm;margin-left: 0cm")
++ assert has_rules(result,".G-fr7","margin-right: 0cm;margin-left: 0cm")
+ assert has_rules(result,".P-Illustration","font-size: 10pt;")
+
+ def test_positioned_shapes(self):
+Index: python-odf-0.9.7/tests/testxmlgen.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testxmlgen.py
++++ python-odf-0.9.7/tests/testxmlgen.py
+@@ -19,7 +19,7 @@
+ #
+
+ import xml.sax, xml.sax.saxutils
+-import StringIO
++import io
+ import unittest
+
+ class MyGen(xml.sax.saxutils.XMLGenerator):
+@@ -41,7 +41,7 @@ class TestXMLGenerator(unittest.TestCase
+
+ def test_xmlgenerator(self):
+ """ Test that the xml namespace is understood by XMLGenerator """
+- outfp = StringIO.StringIO()
++ outfp = io.BytesIO()
+ c = xml.sax.saxutils.XMLGenerator(outfp,'utf-8')
+ parser = xml.sax.make_parser()
+ parser.setFeature(xml.sax.handler.feature_namespaces, 1)
+@@ -56,12 +56,12 @@ class TestXMLGenerator(unittest.TestCase
+ <a:greetings xmlns:a="http://example.com/ns" xmlns:xml="http://www.w3.org/XML/1998/namespace">
+ <a:greet xml:lang="en">Hello world</a:greet>
+ </a:greetings>"""
+- self.assertEqual( outfp.getvalue(), expectedresult)
++ self.assertEqual( outfp.getvalue().decode('utf-8'), expectedresult)
+
+
+ def test_xmlgenerator_wo_ns(self):
+ """ Test that the missing xml namespace is understood by XMLGenerator """
+- outfp = StringIO.StringIO()
++ outfp = io.BytesIO()
+ c = xml.sax.saxutils.XMLGenerator(outfp,'utf-8')
+ parser = xml.sax.make_parser()
+ parser.setFeature(xml.sax.handler.feature_namespaces, 1)
+@@ -76,12 +76,12 @@ class TestXMLGenerator(unittest.TestCase
+ <a:greetings xmlns:a="http://example.com/ns">
+ <a:greet xml:lang="en">Hello world</a:greet>
+ </a:greetings>"""
+- self.assertEqual( outfp.getvalue(), expectedresult)
++ self.assertEqual( outfp.getvalue().decode('utf-8'), expectedresult)
+ # self.assertRaises(KeyError, parser.feed, testcontent)
+
+ def test_myxml(self):
+ """ Test that my patch works """
+- outfp = StringIO.StringIO()
++ outfp = io.BytesIO()
+ c = MyGen(outfp,'utf-8')
+ parser = xml.sax.make_parser()
+ parser.setFeature(xml.sax.handler.feature_namespaces, 1)
+@@ -96,11 +96,11 @@ class TestXMLGenerator(unittest.TestCase
+ <a:greetings xmlns:a="http://example.com/ns" xmlns:xml="http://www.w3.org/XML/1998/namespace">
+ <a:greet xml:lang="en">Hello world</a:greet>
+ </a:greetings>"""
+- self.assertEqual( outfp.getvalue(), expectedresult)
++ self.assertEqual( outfp.getvalue().decode('utf-8'), expectedresult)
+
+ def test_myxml_wo_xml(self):
+ """ Test that my patch understands the missing xml namespace """
+- outfp = StringIO.StringIO()
++ outfp = io.BytesIO()
+ c = MyGen(outfp,'utf-8')
+ parser = xml.sax.make_parser()
+ parser.setFeature(xml.sax.handler.feature_namespaces, 1)
+@@ -115,7 +115,7 @@ class TestXMLGenerator(unittest.TestCase
+ <a:greetings xmlns:a="http://example.com/ns" xmlns:xml="http://www.w3.org/XML/1998/namespace">
+ <a:greet xml:lang="en">Hello world</a:greet>
+ </a:greetings>"""
+- self.assertEqual( outfp.getvalue(), expectedresult)
++ self.assertEqual( outfp.getvalue().decode('utf-8'), expectedresult)
+
+ if __name__ == '__main__':
+ unittest.main()
+Index: python-odf-0.9.7/tests/testdatastyles.py
+===================================================================
+--- python-odf-0.9.7.orig/tests/testdatastyles.py
++++ python-odf-0.9.7/tests/testdatastyles.py
+@@ -33,7 +33,7 @@ class TestDatastyles(unittest.TestCase):
+
+ def tearDown(self):
+ if self.saved:
+- os.unlink("TEST.odt")
++ os.unlink("TEST.ods")
+
+ def test_percentage(self):
+ """ Test that an automatic style can refer to a PercentageStyle as a datastylename """
+@@ -53,13 +53,13 @@ class TestDatastyles(unittest.TestCase):
+ tr.addElement(tc)
+ table.addElement(tr)
+ doc.spreadsheet.addElement(table)
+- doc.save("TEST.odt")
++ doc.save("TEST.ods")
+ self.saved = True
+- d = load("TEST.odt")
++ d = load("TEST.ods")
+ result = d.contentxml()
+- self.assertNotEqual(-1, result.find(u'''<number:percentage-style'''))
+- self.assertNotEqual(-1, result.find(u'''style:data-style-name="N11"'''))
+- self.assertNotEqual(-1, result.find(u'''style:name="pourcent"'''))
++ self.assertNotEqual(-1, result.find('''<number:percentage-style'''))
++ self.assertNotEqual(-1, result.find('''style:data-style-name="N11"'''))
++ self.assertNotEqual(-1, result.find('''style:name="pourcent"'''))
+
+ def test_chart_style(self):
+ """ Test that chart:style-name reference is seen in content.xml """
+@@ -133,7 +133,7 @@ class TestDatastyles(unittest.TestCase):
+ yt.addElement(text.P(text="y_axis"))
+
+ result = doc.contentxml()
+- self.assertNotEqual(-1, result.find(u'''style:family="chart"'''))
++ self.assertNotEqual(-1, result.find('''style:family="chart"'''))
+
+ if __name__ == '__main__':
+ unittest.main()
Added: packages/python-odf/trunk/debian/python-odf-doc.install
===================================================================
--- packages/python-odf/trunk/debian/python-odf-doc.install (rev 0)
+++ packages/python-odf/trunk/debian/python-odf-doc.install 2014-10-21 09:54:57 UTC (rev 31190)
@@ -0,0 +1 @@
+api-for-odfpy.odt usr/share/doc/python-odf-doc/odt
Added: packages/python-odf/trunk/debian/python-odf.install
===================================================================
--- packages/python-odf/trunk/debian/python-odf.install (rev 0)
+++ packages/python-odf/trunk/debian/python-odf.install 2014-10-21 09:54:57 UTC (rev 31190)
@@ -0,0 +1 @@
+build/lib.linux-x86_64-2.7/odf usr/lib/python2.7/dist-packages
Added: packages/python-odf/trunk/debian/python3-odf.install
===================================================================
--- packages/python-odf/trunk/debian/python3-odf.install (rev 0)
+++ packages/python-odf/trunk/debian/python3-odf.install 2014-10-21 09:54:57 UTC (rev 31190)
@@ -0,0 +1,3 @@
+build/lib/odf usr/lib/python3/dist-packages
+build/scripts-3.4/* usr/bin
+usr/share/man/man1/*
\ No newline at end of file
Modified: packages/python-odf/trunk/debian/rules
===================================================================
--- packages/python-odf/trunk/debian/rules 2014-10-21 08:34:37 UTC (rev 31189)
+++ packages/python-odf/trunk/debian/rules 2014-10-21 09:54:57 UTC (rev 31190)
@@ -5,7 +5,7 @@
PYTHON2=$(shell pyversions -vr)
%:
- dh $@ --with python2
+ dh $@ --with python2 --with python3
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
test-python%:
@@ -18,10 +18,23 @@
override_dh_auto_test: $(PYTHON2:%=test-python%)
endif
+
+override_dh_clean:
+ # remove manfiles
+ for D in csv2ods mailodf odf2xhtml odf2mht odf2xml odfimgimport odflint odfmeta odfoutline odfuserfield xml2odf; do \
+ ( cd $$D && \
+ rm -f $$D.1) \
+ done
+ # remove build space
+ rm -rf build
+ # remove generated symlinks
+ rm -f tests/odf
+ dh_clean
+
override_dh_auto_build:
for D in csv2ods mailodf odf2xhtml odf2mht odf2xml odfimgimport odflint odfmeta odfoutline odfuserfield xml2odf; do \
( cd $$D && \
- rm $$D.1 && \
$(MAKE) ) \
done
- dh_auto_build
+ python setup.py build
+ python3 setup.py build
More information about the Python-modules-commits
mailing list