[Checkins] SVN: zope.pagetemplate/trunk/ Port to Py3.3.

Albertas Agejevas cvs-admin at zope.org
Fri Feb 22 16:26:51 UTC 2013


Log message for revision 129661:
  Port to Py3.3.

Changed:
  U   zope.pagetemplate/trunk/setup.py
  U   zope.pagetemplate/trunk/src/zope/pagetemplate/pagetemplate.py
  U   zope.pagetemplate/trunk/src/zope/pagetemplate/pagetemplatefile.py
  U   zope.pagetemplate/trunk/src/zope/pagetemplate/tests/input/checkpathalt.html
  U   zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_basictemplate.py
  U   zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_engine.py
  U   zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_ptfile.py
  U   zope.pagetemplate/trunk/src/zope/pagetemplate/tests/util.py
  U   zope.pagetemplate/trunk/tox.ini

-=-
Modified: zope.pagetemplate/trunk/setup.py
===================================================================
--- zope.pagetemplate/trunk/setup.py	2013-02-22 16:26:42 UTC (rev 129660)
+++ zope.pagetemplate/trunk/setup.py	2013-02-22 16:26:51 UTC (rev 129661)
@@ -104,6 +104,7 @@
           untrusted=['zope.untrustedpython'],
       ),
       install_requires=['setuptools',
+                        'six',
                         'zope.interface',
                         'zope.component',
                         'zope.tales',

Modified: zope.pagetemplate/trunk/src/zope/pagetemplate/pagetemplate.py
===================================================================
--- zope.pagetemplate/trunk/src/zope/pagetemplate/pagetemplate.py	2013-02-22 16:26:42 UTC (rev 129660)
+++ zope.pagetemplate/trunk/src/zope/pagetemplate/pagetemplate.py	2013-02-22 16:26:51 UTC (rev 129661)
@@ -16,6 +16,7 @@
 HTML- and XML-based template objects using TAL, TALES, and METAL.
 """
 import sys
+import six
 from zope.tal.talparser import TALParser
 from zope.tal.htmltalparser import HTMLTALParser
 from zope.tal.talgenerator import TALGenerator
@@ -30,7 +31,6 @@
 from zope.interface import provider
 
 _default_options = {}
-_error_start = '<!-- Page Template Diagnostics'
 
 
 class StringIO(list):
@@ -73,6 +73,9 @@
         to perform the rendering.
     """
 
+    _error_start = '<!-- Page Template Diagnostics'
+    _error_end = '-->'
+    _newline = '\n'
 
     content_type = 'text/html'
     expand = 1
@@ -143,17 +146,28 @@
             except:
                 return ('Macro expansion failed', '%s: %s' % sys.exc_info()[:2])
 
+    def _convert(self, string, text):
+        """Adjust the string type to the type of text"""
+        if isinstance(text, six.binary_type):
+            return string.encode('utf-8')
+        else:
+            return string
+
     def write(self, text):
         # We accept both, since the text can either come from a file (and the
         # parser will take care of the encoding) or from a TTW template, in
         # which case we already have unicode.
-        assert isinstance(text, (str, unicode))
+        assert isinstance(text, (six.string_types, six.binary_type))
 
-        if text.startswith(_error_start):
-            errend = text.find('-->')
+        def bs(s):
+            """Bytes or str"""
+            return self._convert(s, text)
+
+        if text.startswith(bs(self._error_start)):
+            errend = text.find(bs(self._error_end))
             if errend >= 0:
                 text = text[errend + 3:]
-                if text[:1] == "\n":
+                if text[:1] == bs(self._newline):
                     text = text[1:]
         if self._text != text:
             self._text = text
@@ -165,6 +179,9 @@
     def read(self, request=None):
         """Gets the source, sometimes with macros expanded."""
         self._cook_check()
+        def bs(s):
+            """Bytes or str"""
+            return self._convert(s, self._text)
         if not self._v_errors:
             if not self.expand:
                 return self._text
@@ -175,13 +192,13 @@
                 context = self.pt_getContext(self, request)
                 return self.pt_render(context, source=1)
             except:
-                return ('%s\n Macro expansion failed\n %s\n-->\n%s' %
-                        (_error_start, "%s: %s" % sys.exc_info()[:2],
-                         self._text) )
+                return (bs('%s\n Macro expansion failed\n %s\n-->\n' %
+                           (_error_start, "%s: %s" % sys.exc_info()[:2])) +
+                        self._text)
 
-        return ('%s\n %s\n-->\n%s' % (_error_start,
-                                      '\n'.join(self._v_errors),
-                                      self._text))
+        return bs('%s\n %s\n-->\n' % (self._error_start,
+                                      '\n'.join(self._v_errors))) + \
+               self._text
 
     def pt_source_file(self):
         """To be overridden."""

Modified: zope.pagetemplate/trunk/src/zope/pagetemplate/pagetemplatefile.py
===================================================================
--- zope.pagetemplate/trunk/src/zope/pagetemplate/pagetemplatefile.py	2013-02-22 16:26:42 UTC (rev 129660)
+++ zope.pagetemplate/trunk/src/zope/pagetemplate/pagetemplatefile.py	2013-02-22 16:26:51 UTC (rev 129661)
@@ -23,13 +23,14 @@
 import re
 import logging
 
+import six
 from zope.pagetemplate.pagetemplate import PageTemplate
 
 DEFAULT_ENCODING = "utf-8"
 
 meta_pattern = re.compile(
-    r'\s*<meta\s+http-equiv=["\']?Content-Type["\']?'
-    r'\s+content=["\']?([^;]+);\s*charset=([^"\']+)["\']?\s*/?\s*>\s*',
+    br'\s*<meta\s+http-equiv=["\']?Content-Type["\']?'
+    br'\s+content=["\']?([^;]+);\s*charset=([^"\']+)["\']?\s*/?\s*>\s*',
     re.IGNORECASE)
 
 def package_home(gdict):
@@ -41,6 +42,10 @@
 
     _v_last_read = 0
 
+    #_error_start = b'<!-- Page Template Diagnostics'
+    #_error_end = b'-->'
+    #_newline = b'\n'
+
     def __init__(self, filename, _prefix=None):
         path = self.get_path_from_prefix(_prefix)
         self.filename = os.path.join(path, filename)
@@ -59,14 +64,15 @@
     def _prepare_html(self, text):
         match = meta_pattern.search(text)
         if match is not None:
-            type_, encoding = match.groups()
+            type_, encoding = (x.decode('utf-8') for x in match.groups())
             # TODO: Shouldn't <meta>/<?xml?> stripping
             # be in PageTemplate.__call__()?
-            text = meta_pattern.sub("", text)
+            text = meta_pattern.sub(b"", text)
         else:
             type_ = None
             encoding = DEFAULT_ENCODING
-        return unicode(text, encoding), type_
+        text = text.decode(encoding)
+        return text, type_
 
     def _read_file(self):
         __traceback_info__ = self.filename
@@ -77,13 +83,8 @@
             f.close()
             raise
         type_ = sniff_type(text)
-        if type_ == "text/xml":
-            text += f.read()
-        else:
-            # For HTML, we really want the file read in text mode:
-            f.close()
-            f = open(self.filename)
-            text = f.read()
+        text += f.read()
+        if type_ != "text/xml":
             text, type_ = self._prepare_html(text)
         f.close()
         return text, type_
@@ -114,12 +115,12 @@
         raise TypeError("non-picklable object")
 
 XML_PREFIXES = [
-    "<?xml",                      # ascii, utf-8
-    "\xef\xbb\xbf<?xml",          # utf-8 w/ byte order mark
-    "\0<\0?\0x\0m\0l",            # utf-16 big endian
-    "<\0?\0x\0m\0l\0",            # utf-16 little endian
-    "\xfe\xff\0<\0?\0x\0m\0l",    # utf-16 big endian w/ byte order mark
-    "\xff\xfe<\0?\0x\0m\0l\0",    # utf-16 little endian w/ byte order mark
+    b"<?xml",                      # ascii, utf-8
+    b"\xef\xbb\xbf<?xml",          # utf-8 w/ byte order mark
+    b"\0<\0?\0x\0m\0l",            # utf-16 big endian
+    b"<\0?\0x\0m\0l\0",            # utf-16 little endian
+    b"\xfe\xff\0<\0?\0x\0m\0l",    # utf-16 big endian w/ byte order mark
+    b"\xff\xfe<\0?\0x\0m\0l\0",    # utf-16 little endian w/ byte order mark
     ]
 
 XML_PREFIX_MAX_LENGTH = max(map(len, XML_PREFIXES))

Modified: zope.pagetemplate/trunk/src/zope/pagetemplate/tests/input/checkpathalt.html
===================================================================
--- zope.pagetemplate/trunk/src/zope/pagetemplate/tests/input/checkpathalt.html	2013-02-22 16:26:42 UTC (rev 129660)
+++ zope.pagetemplate/trunk/src/zope/pagetemplate/tests/input/checkpathalt.html	2013-02-22 16:26:51 UTC (rev 129661)
@@ -11,7 +11,7 @@
    <p tal:attributes="name y/z | nil">Z</p>
    <p tal:attributes="name y/z | nothing">Z</p>
 
-   <p tal:on-error="python:str(error.value[0])" tal:content="a/b | c/d">Z</p>
+   <p tal:on-error="python:str(error.value.args[0])" tal:content="a/b | c/d">Z</p>
    </div>
 </body>
 </html>

Modified: zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_basictemplate.py
===================================================================
--- zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_basictemplate.py	2013-02-22 16:26:42 UTC (rev 129660)
+++ zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_basictemplate.py	2013-02-22 16:26:51 UTC (rev 129661)
@@ -68,8 +68,8 @@
         self.t.write("<tal:block define='a string:foo'>xyz")
         try:
             self.t.pt_render({})
-        except zope.pagetemplate.pagetemplate.PTRuntimeError, e:
-            self.assertEquals(
+        except zope.pagetemplate.pagetemplate.PTRuntimeError as e:
+            self.assertEqual(
                 str(e),
                 "['Compilation failed', 'zope.tal.taldefs.TALError:"
                 " TAL attributes on <tal:block> require explicit"
@@ -208,11 +208,11 @@
 
         # test with HTML parser
         self.t.pt_edit(text, 'text/html')
-        self.assertEquals(self.t().strip(), text)
+        self.assertEqual(self.t().strip(), text)
 
         # test with XML parser
         self.t.pt_edit(text, 'text/xml')
-        self.assertEquals(self.t().strip(), text)
+        self.assertEqual(self.t().strip(), text)
 
 def test_suite():
     return unittest.makeSuite(BasicTemplateTests)

Modified: zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_engine.py
===================================================================
--- zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_engine.py	2013-02-22 16:26:42 UTC (rev 129660)
+++ zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_engine.py	2013-02-22 16:26:51 UTC (rev 129661)
@@ -13,9 +13,13 @@
 ##############################################################################
 """Doc tests for the pagetemplate's 'engine' module
 """
+import doctest
+import re
 import unittest
 import zope.pagetemplate.engine
+from zope.testing.renormalizing import RENormalizing
 
+
 class DummyNamespace(object):
 
     def __init__(self, context):
@@ -80,10 +84,21 @@
         self.assertRaises(NameError, expr, DummyContext())
 
 
+
 def test_suite():
-    from doctest import DocTestSuite
+
+    checker = RENormalizing([
+        # Python 3 includes module name in exceptions
+        (re.compile(r"zope.security.interfaces.ForbiddenAttribute"),
+         "ForbiddenAttribute"),
+        (re.compile(r"<class 'zope.security._proxy._Proxy'>"),
+         "<type 'zope.security._proxy._Proxy'>"),
+        (re.compile(r"<class 'list'>"), "<type 'list'>"),
+    ])
+
     suite = unittest.TestSuite()
-    suite.addTest(DocTestSuite('zope.pagetemplate.engine'))
+    suite.addTest(doctest.DocTestSuite('zope.pagetemplate.engine',
+                                       checker=checker))
     suite.addTest(unittest.makeSuite(EngineTests))
     if zope.pagetemplate.engine.HAVE_UNTRUSTED:
         suite.addTest(unittest.makeSuite(ZopePythonExprTests))

Modified: zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_ptfile.py
===================================================================
--- zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_ptfile.py	2013-02-22 16:26:42 UTC (rev 129660)
+++ zope.pagetemplate/trunk/src/zope/pagetemplate/tests/test_ptfile.py	2013-02-22 16:26:51 UTC (rev 129661)
@@ -17,6 +17,7 @@
 import tempfile
 import unittest
 
+import six
 from zope.pagetemplate.pagetemplatefile import PageTemplateFile
 
 
@@ -42,78 +43,78 @@
 
     def test_sniffer_xml_ascii(self):
         self.check_content_type(
-            "<?xml version='1.0' encoding='ascii'?><doc/>",
+            b"<?xml version='1.0' encoding='ascii'?><doc/>",
             "text/xml")
         self.check_content_type(
-            "<?xml\tversion='1.0' encoding='ascii'?><doc/>",
+            b"<?xml\tversion='1.0' encoding='ascii'?><doc/>",
             "text/xml")
 
     def test_sniffer_xml_utf8(self):
         # w/out byte order mark
         self.check_content_type(
-            "<?xml version='1.0' encoding='utf-8'?><doc/>",
+            b"<?xml version='1.0' encoding='utf-8'?><doc/>",
             "text/xml")
         self.check_content_type(
-            "<?xml\tversion='1.0' encoding='utf-8'?><doc/>",
+            b"<?xml\tversion='1.0' encoding='utf-8'?><doc/>",
             "text/xml")
         # with byte order mark
         self.check_content_type(
-            "\xef\xbb\xbf<?xml version='1.0' encoding='utf-8'?><doc/>",
+            b"\xef\xbb\xbf<?xml version='1.0' encoding='utf-8'?><doc/>",
             "text/xml")
         self.check_content_type(
-            "\xef\xbb\xbf<?xml\tversion='1.0' encoding='utf-8'?><doc/>",
+            b"\xef\xbb\xbf<?xml\tversion='1.0' encoding='utf-8'?><doc/>",
             "text/xml")
 
     def test_sniffer_xml_utf16_be(self):
         # w/out byte order mark
         self.check_content_type(
-            "\0<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'"
-            "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>"
-            "\0<\0d\0o\0c\0/\0>",
+            b"\0<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'"
+            b"\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>"
+            b"\0<\0d\0o\0c\0/\0>",
             "text/xml")
         self.check_content_type(
-            "\0<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'"
-            "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>"
-            "\0<\0d\0o\0c\0/\0>",
+            b"\0<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'"
+            b"\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>"
+            b"\0<\0d\0o\0c\0/\0>",
             "text/xml")
         # with byte order mark
         self.check_content_type(
-            "\xfe\xff"
-            "\0<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'"
-            "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>"
-            "\0<\0d\0o\0c\0/\0>",
+            b"\xfe\xff"
+            b"\0<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'"
+            b"\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>"
+            b"\0<\0d\0o\0c\0/\0>",
             "text/xml")
         self.check_content_type(
-            "\xfe\xff"
-            "\0<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'"
-            "\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>"
-            "\0<\0d\0o\0c\0/\0>",
+            b"\xfe\xff"
+            b"\0<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'"
+            b"\0 \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>"
+            b"\0<\0d\0o\0c\0/\0>",
             "text/xml")
 
     def test_sniffer_xml_utf16_le(self):
         # w/out byte order mark
         self.check_content_type(
-            "<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0"
-            " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0"
-            "<\0d\0o\0c\0/\0>\n",
+            b"<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0"
+            b" \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0"
+            b"<\0d\0o\0c\0/\0>\n",
             "text/xml")
         self.check_content_type(
-            "<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0"
-            " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0"
-            "<\0d\0o\0c\0/\0>\0",
+            b"<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0"
+            b" \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0"
+            b"<\0d\0o\0c\0/\0>\0",
             "text/xml")
         # with byte order mark
         self.check_content_type(
-            "\xff\xfe"
-            "<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0"
-            " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0"
-            "<\0d\0o\0c\0/\0>\0",
+            b"\xff\xfe"
+            b"<\0?\0x\0m\0l\0 \0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0"
+            b" \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0"
+            b"<\0d\0o\0c\0/\0>\0",
             "text/xml")
         self.check_content_type(
-            "\xff\xfe"
-            "<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0"
-            " \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0"
-            "<\0d\0o\0c\0/\0>\0",
+            b"\xff\xfe"
+            b"<\0?\0x\0m\0l\0\t\0v\0e\0r\0s\0i\0o\0n\0=\0'\01\0.\0000\0'\0"
+            b" \0e\0n\0c\0o\0d\0i\0n\0g\0=\0'\0u\0t\0f\0-\08\0'\0?\0>\0"
+            b"<\0d\0o\0c\0/\0>\0",
             "text/xml")
 
     HTML_PUBLIC_ID = "-//W3C//DTD HTML 4.01 Transitional//EN"
@@ -121,11 +122,11 @@
 
     def test_sniffer_html_ascii(self):
         self.check_content_type(
-            "<!DOCTYPE html [ SYSTEM '%s' ]><html></html>"
-            % self.HTML_SYSTEM_ID,
+            ("<!DOCTYPE html [ SYSTEM '%s' ]><html></html>"
+            % self.HTML_SYSTEM_ID).encode("utf-8"),
             "text/html")
         self.check_content_type(
-            "<html><head><title>sample document</title></head></html>",
+            b"<html><head><title>sample document</title></head></html>",
             "text/html")
 
     # TODO: This reflects a case that simply isn't handled by the
@@ -137,43 +138,43 @@
 
     def test_html_default_encoding(self):
         pt = self.get_pt(
-            "<html><head><title>"
+            b"<html><head><title>"
             # 'Test' in russian (utf-8)
-            "\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82"
-            "</title></head></html>")
+            b"\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82"
+            b"</title></head></html>")
         rendered = pt()
-        self.failUnless(isinstance(rendered, unicode))
-        self.failUnlessEqual(rendered.strip(),
+        self.assertTrue(isinstance(rendered, six.text_type))
+        self.assertEqual(rendered.strip(),
             u"<html><head><title>"
             u"\u0422\u0435\u0441\u0442"
             u"</title></head></html>")
 
     def test_html_encoding_by_meta(self):
         pt = self.get_pt(
-            "<html><head><title>"
+            b"<html><head><title>"
             # 'Test' in russian (windows-1251)
-            "\xd2\xe5\xf1\xf2"
-            '</title><meta http-equiv="Content-Type"'
-            ' content="text/html; charset=windows-1251">'
-            "</head></html>")
+            b"\xd2\xe5\xf1\xf2"
+            b'</title><meta http-equiv="Content-Type"'
+            b' content="text/html; charset=windows-1251">'
+            b"</head></html>")
         rendered = pt()
-        self.failUnless(isinstance(rendered, unicode))
-        self.failUnlessEqual(rendered.strip(),
+        self.assertTrue(isinstance(rendered, six.text_type))
+        self.assertEqual(rendered.strip(),
             u"<html><head><title>"
             u"\u0422\u0435\u0441\u0442"
             u"</title></head></html>")
 
     def test_xhtml(self):
         pt = self.get_pt(
-            "<html><head><title>"
+            b"<html><head><title>"
             # 'Test' in russian (windows-1251)
-            "\xd2\xe5\xf1\xf2"
-            '</title><meta http-equiv="Content-Type"'
-            ' content="text/html; charset=windows-1251"/>'
-            "</head></html>")
+            b"\xd2\xe5\xf1\xf2"
+            b'</title><meta http-equiv="Content-Type"'
+            b' content="text/html; charset=windows-1251"/>'
+            b"</head></html>")
         rendered = pt()
-        self.failUnless(isinstance(rendered, unicode))
-        self.failUnlessEqual(rendered.strip(),
+        self.assertTrue(isinstance(rendered, six.text_type))
+        self.assertEqual(rendered.strip(),
             u"<html><head><title>"
             u"\u0422\u0435\u0441\u0442"
             u"</title></head></html>")

Modified: zope.pagetemplate/trunk/src/zope/pagetemplate/tests/util.py
===================================================================
--- zope.pagetemplate/trunk/src/zope/pagetemplate/tests/util.py	2013-02-22 16:26:42 UTC (rev 129660)
+++ zope.pagetemplate/trunk/src/zope/pagetemplate/tests/util.py	2013-02-22 16:26:51 UTC (rev 129661)
@@ -13,6 +13,7 @@
 ##############################################################################
 """Utilities
 """
+from __future__ import print_function
 import os
 import re
 import sys
@@ -70,7 +71,7 @@
 
 def dump(tag, x, lo, hi):
     for i in xrange(lo, hi):
-        print '%s %s' % (tag, x[i]),
+        print('%s %s' % (tag, x[i]), end=' ')
 
 def check_html(s1, s2):
     s1 = normalize_html(s1)

Modified: zope.pagetemplate/trunk/tox.ini
===================================================================
--- zope.pagetemplate/trunk/tox.ini	2013-02-22 16:26:42 UTC (rev 129660)
+++ zope.pagetemplate/trunk/tox.ini	2013-02-22 16:26:51 UTC (rev 129661)
@@ -1,7 +1,7 @@
 [tox]
 envlist =
     # py32 needs a py3k-compatible zope.security at the very least
-    py26,py27
+    py26,py27,py33
 
 [testenv]
 deps =



More information about the checkins mailing list