Commits

xpahos committed b492a4c

Initial commit with fixes for Python 3.2

  • Participants
  • Parent commits acfb178

Comments (0)

Files changed (24)

File tests/test_containers.py

     eq_(d2["bar"], 2)
     eq_(d2[42], [])
     assert "foo" in d2
-    assert "foo" in d2.keys()
+    assert "foo" in list(d2.keys())
     assert "bar" in d2
-    assert "bar" in d2.keys()
+    assert "bar" in list(d2.keys())
     assert 42 in d2
-    assert 42 in d2.keys()
+    assert 42 in list(d2.keys())
     assert 12 not in d2
-    assert 12 not in d2.keys()
+    assert 12 not in list(d2.keys())
     d2.default_factory = None
     eq_(d2.default_factory, None)
     try:
         d2[15]
-    except KeyError, err:
+    except KeyError as err:
         eq_(err.args, (15,))
     else:
         message = "d2[15] didn't raise KeyError"
     try:
         f = open(tfn, "w+")
         try:
-            print >>f, d1
-            print >>f, d2
+            print(d1, file=f)
+            print(d2, file=f)
             f.seek(0)
             eq_(f.readline(), repr(d1) + "\n")
             eq_(f.readline(), repr(d2) + "\n")

File tests/test_converters.py

 [Michel Fortin][] has ported to Markdown to PHP.
     """
     if _markdown.version_info >= (2, 0):
-        expected =  literal(u'<h2>Introduction</h2>\n<p>Markdown is a text-to-HTML conversion tool for web writers.</p>\n<h2>Acknowledgements <a id="acknowledgements" /></h2>\n<p>[Michel Fortin][] has ported to Markdown to PHP.</p>')
+        expected =  literal('<h2>Introduction</h2>\n<p>Markdown is a text-to-HTML conversion tool for web writers.</p>\n<h2>Acknowledgements <a id="acknowledgements" /></h2>\n<p>[Michel Fortin][] has ported to Markdown to PHP.</p>')
     else:
-        expected =  literal(u'<h2>Introduction</h2>\n<p>Markdown is a text-to-HTML conversion tool for web writers.\n</p>\n\n<h2>Acknowledgements <a id="acknowledgements" /></h2>\n<p>[Michel Fortin][] has ported to Markdown to PHP.\n</p>')
+        expected =  literal('<h2>Introduction</h2>\n<p>Markdown is a text-to-HTML conversion tool for web writers.\n</p>\n\n<h2>Acknowledgements <a id="acknowledgements" /></h2>\n<p>[Michel Fortin][] has ported to Markdown to PHP.\n</p>')
     eq_(markdown(markdown_text, markdown=_markdown), expected)
 
 def test_markdown_embedded_html():
     _markdown = _get_markdown_module()
     markdown_text = 'This text includes <script>Javascript</script> & stuff.'
     if _markdown.version_info >= (2, 0):
-        expected = literal(u'<p>This text includes &lt;script&gt;Javascript&lt;/script&gt; &amp; stuff.</p>')
+        expected = literal('<p>This text includes &lt;script&gt;Javascript&lt;/script&gt; &amp; stuff.</p>')
     else:
-        expected = literal(u'<p>This text includes &lt;script&gt;Javascript&lt;/script&gt; &amp; stuff.\n</p>')
+        expected = literal('<p>This text includes &lt;script&gt;Javascript&lt;/script&gt; &amp; stuff.\n</p>')
     eq_(markdown(markdown_text, safe_mode="escape", markdown=_markdown), expected)
 
 
 def test_nl2br():
-    eq_(u'A B<br />\nC D<br />\n<br />\nE F', nl2br("A B\nC D\r\n\r\nE F"))
+    eq_('A B<br />\nC D<br />\n<br />\nE F', nl2br("A B\nC D\r\n\r\nE F"))
 
 def test_nl2br2():
-    eq_(u'&lt;strike&gt;W&lt;/strike&gt;<br />\nThe W', nl2br("<strike>W</strike>\nThe W"))
+    eq_('&lt;strike&gt;W&lt;/strike&gt;<br />\nThe W', nl2br("<strike>W</strike>\nThe W"))
 
 def test_nl2br3():
-    eq_(u'<strike>W</strike><br />\nThe W', nl2br(literal("<strike>W</strike>\nThe W")))
+    eq_('<strike>W</strike><br />\nThe W', nl2br(literal("<strike>W</strike>\nThe W")))
 
 def test_format_paragraphs1():
-    eq_(u"<p>crazy\n cross\n platform linebreaks</p>", format_paragraphs("crazy\r\n cross\r platform linebreaks"))
+    eq_("<p>crazy\n cross\n platform linebreaks</p>", format_paragraphs("crazy\r\n cross\r platform linebreaks"))
 
 def test_format_paragraphs2():
-    eq_(u"<p>crazy<br />\n cross<br />\n platform linebreaks</p>", format_paragraphs("crazy\r\n cross\r platform linebreaks", True))
+    eq_("<p>crazy<br />\n cross<br />\n platform linebreaks</p>", format_paragraphs("crazy\r\n cross\r platform linebreaks", True))
 
 def test_format_paragraphs3():
-    eq_(u"<p>A paragraph</p>\n\n<p>and another one!</p>", format_paragraphs("A paragraph\n\nand another one!"))
+    eq_("<p>A paragraph</p>\n\n<p>and another one!</p>", format_paragraphs("A paragraph\n\nand another one!"))
 
 def test_format_paragraphs4():
-    eq_(u"<p>A paragraph<br />\n With a newline</p>", format_paragraphs("A paragraph\n With a newline", True))
+    eq_("<p>A paragraph<br />\n With a newline</p>", format_paragraphs("A paragraph\n With a newline", True))
 
 def test_format_paragraphs5():
-    eq_(u"<p>A paragraph\n With a newline</p>", format_paragraphs("A paragraph\n With a newline", False))
+    eq_("<p>A paragraph\n With a newline</p>", format_paragraphs("A paragraph\n With a newline", False))
 
 def test_format_paragraphs6():
-    eq_(u"<p>A paragraph\n With a newline</p>", format_paragraphs("A paragraph\n With a newline"))
+    eq_("<p>A paragraph\n With a newline</p>", format_paragraphs("A paragraph\n With a newline"))
 
 def test_format_paragraphs7():
-    eq_(u"", format_paragraphs(None))
+    eq_("", format_paragraphs(None))

File tests/test_escapes.py

+from nose.tools import eq_
 from webhelpers.util import *
 
 def test_html_escape():
-    assert html_escape('foo') == 'foo'
-    assert html_escape('<this"that>') == '&lt;this&quot;that&gt;'
-    assert html_escape(u'\u1000') == '&#4096;'
+    eq_(html_escape('foo'), 'foo')
+    eq_(html_escape('<this"that>'), '&lt;this&quot;that&gt;')
+    eq_(html_escape('\u1000'), '&#4096;')
     class X:
-        def __unicode__(self):
-            return u'<\u1000>'
-    assert html_escape(X()) == '&lt;&#4096;&gt;'
-    assert html_escape(1) == '1'
-    assert html_escape(None) == ''
+        def __str__(self):
+            return '<\u1000>'
+    eq_(html_escape(X()), '&lt;&#4096;&gt;')
+    eq_(html_escape(1), '1')
+    eq_(html_escape(None), '')

File tests/test_feedgenerator.py

 def test_simple_feed():
     pubdate = datetime.datetime(2009, 12, 18, 23, 45, 12)
     feed = fg.Rss201rev2Feed(
-        title=u"Poynter E-Media Tidbits",
-        link=u"http://www.poynter.org/column.asp?id=31",
-        description=u"A group weblog by the sharpest minds in online media/journalism/publishing.",
-        language=u"en",
+        title="Poynter E-Media Tidbits",
+        link="http://www.poynter.org/column.asp?id=31",
+        description="A group weblog by the sharpest minds in online media/journalism/publishing.",
+        language="en",
     )
     feed.add_item(
         title="Hello", 
-        link=u"http://www.holovaty.com/test/",
+        link="http://www.holovaty.com/test/",
         description="Testing.",  
         pubdate=pubdate)
     result = feed.writeString("utf-8")
 def test_escaping():
     pubdate = datetime.datetime(2009, 12, 18, 23, 45, 12)
     feed = fg.Rss201rev2Feed(
-        title=u"Poynter E-Media Tidbits",
-        link=u"http://www.poynter.org/column.asp?id=31",
-        description=u"A group weblog by the <em>sharpest</em> minds in online media & journalism.",
-        language=u"en",
+        title="Poynter E-Media Tidbits",
+        link="http://www.poynter.org/column.asp?id=31",
+        description="A group weblog by the <em>sharpest</em> minds in online media & journalism.",
+        language="en",
     )
     feed.add_item(
         title="Hello", 
-        link=u"http://www.holovaty.com/test/",
+        link="http://www.holovaty.com/test/",
         description="Testing.",  
         pubdate=pubdate)
     result = feed.writeString("utf-8")
 def test_geo_point_feed():
     pubdate = datetime.datetime(2009, 12, 18, 23, 45, 12)
     feed = fg.GeoAtom1Feed(
-        title=u"Poynter E-Media Tidbits",
-        link=u"http://www.poynter.org/column.asp?id=31",
-        description=u"A group weblog by the sharpest minds in online media/journalism/publishing.",
-        language=u"en",
+        title="Poynter E-Media Tidbits",
+        link="http://www.poynter.org/column.asp?id=31",
+        description="A group weblog by the sharpest minds in online media/journalism/publishing.",
+        language="en",
     )
     feed.add_item(
         title="Hello", 
-        link=u"http://www.holovaty.com/test/",
+        link="http://www.holovaty.com/test/",
         description="Testing.",  
         pubdate=pubdate,
         geometry=(-120.5, 50.5))
 def test_geo_point_feed_longitude_first():
     pubdate = datetime.datetime(2009, 12, 18, 23, 45, 12)
     feed = fg.GeoAtom1Feed(
-        title=u"Poynter E-Media Tidbits",
-        link=u"http://www.poynter.org/column.asp?id=31",
-        description=u"A group weblog by the sharpest minds in online media/journalism/publishing.",
-        language=u"en",
+        title="Poynter E-Media Tidbits",
+        link="http://www.poynter.org/column.asp?id=31",
+        description="A group weblog by the sharpest minds in online media/journalism/publishing.",
+        language="en",
     )
     feed.is_input_latitude_first = False
     feed.add_item(
         title="Hello", 
-        link=u"http://www.holovaty.com/test/",
+        link="http://www.holovaty.com/test/",
         description="Testing.",  
         pubdate=pubdate,
         geometry=(50.5, -120.5))

File tests/test_html.py

 from webhelpers.html import literal, lit_sub, escape, HTML
 
 def test_double_escape():
-    quoted = escape(u'This string is "quoted"')
-    eq_(quoted, u'This string is &#34;quoted&#34;')
+    quoted = escape('This string is "quoted"')
+    eq_(quoted, 'This string is &#34;quoted&#34;')
     dbl_quoted = escape(quoted)
     eq_(quoted, dbl_quoted)
 
 def test_literal():
-    lit = literal(u'This string <>')
-    other = literal(u'<other>')
-    eq_(u'This string <><other>', lit + other)
+    lit = literal('This string <>')
+    other = literal('<other>')
+    eq_('This string <><other>', lit + other)
     assert type(lit + other) is literal
     
-    eq_(u'&#34;<other>', '"' + other)
-    eq_(u'<other>&#34;', other + '"')
+    eq_('&#34;<other>', '"' + other)
+    eq_('<other>&#34;', other + '"')
     
     mod = literal('<%s>ello')
-    eq_(u'<&lt;H&gt;>ello', mod % '<H>')
+    eq_('<&lt;H&gt;>ello', mod % '<H>')
     assert type(mod % '<H>') is literal
     eq_(HTML('<a>'), '&lt;a&gt;')
     assert type(HTML('<a>')) is literal
 
 def test_literal_dict():
-    lit = literal(u'This string <>')
+    lit = literal('This string <>')
     unq = 'This has <crap>'
     sub = literal('%s and %s')
-    eq_(u'This string <> and This has &lt;crap&gt;', sub % (lit, unq))
+    eq_('This string <> and This has &lt;crap&gt;', sub % (lit, unq))
     
     sub = literal('%(lit)s and %(lit)r')
-    eq_(u"This string <> and literal(u&#39;This string &lt;&gt;&#39;)", sub % dict(lit=lit))
+    eq_("This string <> and literal(&#39;This string &lt;&gt;&#39;)", sub % dict(lit=lit))
     sub = literal('%(unq)r and %(unq)s')
-    eq_(u"&#39;This has &lt;crap&gt;&#39; and This has &lt;crap&gt;", sub % dict(unq=unq))
+    eq_("&#39;This has &lt;crap&gt;&#39; and This has &lt;crap&gt;", sub % dict(unq=unq))
 
 def test_literal_mul():
-    lit = literal(u'<>')
-    eq_(u'<><><>', lit * 3)
+    lit = literal('<>')
+    eq_('<><><>', lit * 3)
     assert isinstance(lit*3, literal)
 
 def test_literal_join():
-    lit = literal(u'<>')
+    lit = literal('<>')
     assert isinstance(lit.join(['f', 'a']), literal)
-    eq_(u'f<>a', lit.join(('f', 'a')))
+    eq_('f<>a', lit.join(('f', 'a')))
 
 def test_literal_int():
-    lit = literal(u'<%i>')
-    eq_(u'<5>', lit % 5)
+    lit = literal('<%i>')
+    eq_('<5>', lit % 5)
 
 def test_html():
     a = HTML.a(href='http://mostlysafe\" <tag', c="Bad <script> tag")
-    eq_(a, u'<a href="http://mostlysafe&#34; &lt;tag">Bad &lt;script&gt; tag</a>')
+    eq_(a, '<a href="http://mostlysafe&#34; &lt;tag">Bad &lt;script&gt; tag</a>')
     
     img = HTML.img(src='http://some/image.jpg')
-    eq_(img, u'<img src="http://some/image.jpg" />')
+    eq_(img, '<img src="http://some/image.jpg" />')
     
     br = HTML.br()
-    eq_(u'<br />', br)
+    eq_('<br />', br)
 
 def test_lit_re():
     lit = literal('This is a <string>')
     unlit = 'This is also a <string>'
     
     result = lit_sub(r'<str', literal('<b'), lit)
-    eq_(u'This is a <bing>', escape(result))
+    eq_('This is a <bing>', escape(result))
     
     result = lit_sub(r'a <str', 'a <b> <b', unlit)
-    eq_(u'This is also a &lt;b&gt; &lt;bing&gt;', escape(result))
+    eq_('This is also a &lt;b&gt; &lt;bing&gt;', escape(result))
 
 def test_unclosed_tag():
     result = HTML.form(_closed=False)
-    print result
-    eq_(u'<form>', result)
+    print(result)
+    eq_('<form>', result)
     
     result = HTML.form(_closed=False, action="hello")
-    eq_(u'<form action="hello">', result)
+    eq_('<form action="hello">', result)
 
 def test_newline_arg():
-    eq_(HTML.a(),         literal(u'<a></a>'))
-    eq_(HTML.a(_nl=True), literal(u'<a>\n</a>\n'))
-    eq_(HTML.a(_closed=False),           literal(u'<a>'))
-    eq_(HTML.a(_closed=False, _nl=True), literal(u'<a>\n'))
-    eq_(HTML.a("A", "B", href="/"),      literal(u'<a href="/">AB</a>'))
-    eq_(HTML.a("A", "B", href="/", _nl=True), literal(u'<a href="/">\nA\nB\n</a>\n'))
+    eq_(HTML.a(),         literal('<a></a>'))
+    eq_(HTML.a(_nl=True), literal('<a>\n</a>\n'))
+    eq_(HTML.a(_closed=False),           literal('<a>'))
+    eq_(HTML.a(_closed=False, _nl=True), literal('<a>\n'))
+    eq_(HTML.a("A", "B", href="/"),      literal('<a href="/">AB</a>'))
+    eq_(HTML.a("A", "B", href="/", _nl=True), literal('<a href="/">\nA\nB\n</a>\n'))

File tests/test_modeltags.py

 
 class Holder(object):
     def __init__(self, settings):
-        for k,v in settings.iteritems():
+        for k,v in settings.items():
             setattr(self, k, v)
             
 class TestModelTagsHelperWithObject(WebHelpersTestCase):
     def test_check_box(self):
         self.assertEqual(
             self.m.checkbox("fulltime"),
-            u'<input checked="checked" id="fulltime" name="fulltime" type="checkbox" value="1" />',
+            '<input checked="checked" id="fulltime" name="fulltime" type="checkbox" value="1" />',
         )
 
     def test_hidden_field(self):
         self.assertEqual(
             self.m.hidden("name"),
-            u'<input id="name" name="name" type="hidden" value="Jim" />'
+            '<input id="name" name="name" type="hidden" value="Jim" />'
         )
 
     def test_password_field(self):
         self.assertEqual(
             self.m.password('name'), 
-            u'<input id="name" name="name" type="password" value="Jim" />'
+            '<input id="name" name="name" type="password" value="Jim" />'
         )
     def test_file_field(self):
         self.assertEqual(
             self.m.file('name'), 
-            u'<input id="name" name="name" type="file" value="Jim" />'
+            '<input id="name" name="name" type="file" value="Jim" />'
         )
 
     def test_radio_button(self):
         self.assertEqual(
             self.m.radio("favcolor", "blue"),
-            u'<input checked="checked" id="favcolor_blue" name="favcolor" type="radio" value="blue" />'
+            '<input checked="checked" id="favcolor_blue" name="favcolor" type="radio" value="blue" />'
         )
         
         self.assertEqual(
             self.m.radio("favcolor", "red"),
-            u'<input id="favcolor_red" name="favcolor" type="radio" value="red" />'
+            '<input id="favcolor_red" name="favcolor" type="radio" value="red" />'
         )
 
 
     def test_text_area(self):
         self.assertEqual(
             self.m.textarea("longtext"),
-            u'<textarea id="longtext" name="longtext">lorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\n</textarea>'
+            '<textarea id="longtext" name="longtext">lorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\n</textarea>'
         )
 
     def test_text_field(self):
         self.assertEqual(
             self.m.text("name"),
-            u'<input id="name" name="name" type="text" value="Jim" />'
+            '<input id="name" name="name" type="text" value="Jim" />'
         )
     def test_select(self):
         self.assertEqual(
             self.m.select("lang", [("en", "English"), ("de", "German"), ("jp", "Japanese")]),
-            u'<select id="lang" name="lang">\n<option selected="selected" value="en">English</option>\n<option value="de">German</option>\n<option value="jp">Japanese</option>\n</select>'
+            '<select id="lang" name="lang">\n<option selected="selected" value="en">English</option>\n<option value="de">German</option>\n<option value="jp">Japanese</option>\n</select>'
         )
 
 class TestModelTagsHelperWithDict(TestModelTagsHelperWithObject):
     def test_check_box(self):
         self.assertEqual(
             self.m.checkbox("fulltime"),
-            u'<input checked="checked" id="fulltime" name="fulltime" type="checkbox" value="1" />',
+            '<input checked="checked" id="fulltime" name="fulltime" type="checkbox" value="1" />',
         )
 
     def test_hidden_field(self):
         self.assertEqual(
             self.m.hidden("name"),
-            u'<input id="name" name="name" type="hidden" value="Jim" />'
+            '<input id="name" name="name" type="hidden" value="Jim" />'
         )
 
     def test_password_field(self):
         self.assertEqual(
             self.m.password('name'), 
-            u'<input id="name" name="name" type="password" value="Jim" />'
+            '<input id="name" name="name" type="password" value="Jim" />'
         )
     def test_file_field(self):
         self.assertEqual(
             self.m.file('name'), 
-            u'<input id="name" name="name" type="file" value="Jim" />'
+            '<input id="name" name="name" type="file" value="Jim" />'
         )
 
     def test_radio_button(self):
         self.assertEqual(
             self.m.radio("favcolor", "blue"),
-            u'<input checked="checked" id="favcolor_blue" name="favcolor" type="radio" value="blue" />'
+            '<input checked="checked" id="favcolor_blue" name="favcolor" type="radio" value="blue" />'
         )
 
         self.assertEqual(
             self.m.radio("favcolor", "red"),
-            u'<input id="favcolor_red" name="favcolor" type="radio" value="red" />'
+            '<input id="favcolor_red" name="favcolor" type="radio" value="red" />'
         )
 
 
     def test_text_area(self):
         self.assertEqual(
             self.m.textarea("longtext"),
-            u'<textarea id="longtext" name="longtext">lorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\n</textarea>'
+            '<textarea id="longtext" name="longtext">lorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\n</textarea>'
         )
 
     def test_text_field(self):
         self.assertEqual(
             self.m.text("name"),
-            u'<input id="name" name="name" type="text" value="Jim" />'
+            '<input id="name" name="name" type="text" value="Jim" />'
         )
     def test_select(self):
         self.assertEqual(
             self.m.select("lang", [("en", "English"), ("de", "German"), ("jp", "Japanese")]),
-            u'<select id="lang" name="lang">\n<option selected="selected" value="en">English</option>\n<option value="de">German</option>\n<option value="jp">Japanese</option>\n</select>'
+            '<select id="lang" name="lang">\n<option selected="selected" value="en">English</option>\n<option value="de">German</option>\n<option value="jp">Japanese</option>\n</select>'
         )
 
 class TestModelTagsHelperWithIdGeneration(TestModelTagsHelperWithObject):
     def test_check_box(self):
         self.assertEqual(
             self.m.checkbox("fulltime"),
-            u'<input checked="checked" id="person:fulltime" name="fulltime" type="checkbox" value="1" />',
+            '<input checked="checked" id="person:fulltime" name="fulltime" type="checkbox" value="1" />',
         )
 
     def test_hidden_field(self):
         self.assertEqual(
             self.m.hidden("name"),
-            u'<input id="person:name" name="name" type="hidden" value="Jim" />'
+            '<input id="person:name" name="name" type="hidden" value="Jim" />'
         )
 
     def test_password_field(self):
         self.assertEqual(
             self.m.password('name'), 
-            u'<input id="person:name" name="name" type="password" value="Jim" />'
+            '<input id="person:name" name="name" type="password" value="Jim" />'
         )
     def test_file_field(self):
         self.assertEqual(
             self.m.file('name'), 
-            u'<input id="person:name" name="name" type="file" value="Jim" />'
+            '<input id="person:name" name="name" type="file" value="Jim" />'
         )
 
     def test_radio_button(self):
         self.assertEqual(
             self.m.radio("favcolor", "blue"),
-            u'<input checked="checked" id="person:favcolor_blue" name="favcolor" type="radio" value="blue" />'
+            '<input checked="checked" id="person:favcolor_blue" name="favcolor" type="radio" value="blue" />'
         )
 
         self.assertEqual(
             self.m.radio("favcolor", "red"),
-            u'<input id="person:favcolor_red" name="favcolor" type="radio" value="red" />'
+            '<input id="person:favcolor_red" name="favcolor" type="radio" value="red" />'
         )
 
 
     def test_text_area(self):
         self.assertEqual(
             self.m.textarea("longtext"),
-            u'<textarea id="person:longtext" name="longtext">lorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\n</textarea>'
+            '<textarea id="person:longtext" name="longtext">lorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\nlorem ipsum lorem ipsum\n</textarea>'
         )
 
     def test_text_field(self):
         self.assertEqual(
             self.m.text("name"),
-            u'<input id="person:name" name="name" type="text" value="Jim" />'
+            '<input id="person:name" name="name" type="text" value="Jim" />'
         )
     def test_select(self):
         self.assertEqual(
             self.m.select("lang", [("en", "English"), ("de", "German"), ("jp", "Japanese")]),
-            u'<select id="person:lang" name="lang">\n<option selected="selected" value="en">English</option>\n<option value="de">German</option>\n<option value="jp">Japanese</option>\n</select>'
+            '<select id="person:lang" name="lang">\n<option selected="selected" value="en">English</option>\n<option value="de">German</option>\n<option value="jp">Japanese</option>\n</select>'
         )
 
 class TestModelTagsHelperWithoutObject(WebHelpersTestCase):
     def test_check_box(self):
         self.assertEqual(
             self.m.checkbox("fulltime"),
-            u'<input id="fulltime" name="fulltime" type="checkbox" value="1" />',
+            '<input id="fulltime" name="fulltime" type="checkbox" value="1" />',
         )
 
     def test_hidden_field(self):
         self.assertEqual(
             self.m.hidden("name"),
-            u'<input id="name" name="name" type="hidden" value="" />'
+            '<input id="name" name="name" type="hidden" value="" />'
         )
 
     def test_password_field(self):
         self.assertEqual(
             self.m.password('name'), 
-            u'<input id="name" name="name" type="password" value="" />'
+            '<input id="name" name="name" type="password" value="" />'
         )
     def test_file_field(self):
         self.assertEqual(
             self.m.file('name'), 
-            u'<input id="name" name="name" type="file" value="" />'
+            '<input id="name" name="name" type="file" value="" />'
         )
 
     def test_radio_button(self):
         self.assertEqual(
             self.m.radio("favcolor", "blue"),
-            u'<input id="favcolor_blue" name="favcolor" type="radio" value="blue" />'
+            '<input id="favcolor_blue" name="favcolor" type="radio" value="blue" />'
         )
         
         self.assertEqual(
             self.m.radio("favcolor", "red"),
-            u'<input id="favcolor_red" name="favcolor" type="radio" value="red" />'
+            '<input id="favcolor_red" name="favcolor" type="radio" value="red" />'
         )
 
 
     def test_text_area(self):
         self.assertEqual(
             self.m.textarea("longtext"),
-            u'<textarea id="longtext" name="longtext"></textarea>'
+            '<textarea id="longtext" name="longtext"></textarea>'
         )
 
     def test_text_field(self):
         self.assertEqual(
             self.m.text("name"),
-            u'<input id="name" name="name" type="text" value="" />'
+            '<input id="name" name="name" type="text" value="" />'
         )
     def test_select(self):
         self.assertEqual(
             self.m.select("lang", [("en", "English"), ("de", "German"), ("jp", "Japanese")]),
-            u'<select id="lang" name="lang">\n<option value="en">English</option>\n<option value="de">German</option>\n<option value="jp">Japanese</option>\n</select>'
+            '<select id="lang" name="lang">\n<option value="en">English</option>\n<option value="de">German</option>\n<option value="jp">Japanese</option>\n</select>'
         )        
 if __name__ == '__main__':
-    suite = map(unittest.makeSuite, [
+    suite = list(map(unittest.makeSuite, [
         TestModelTagsHelperWithObject,
         TestModelTagsHelperWithDict,
         TestModelTagsHelperWithIdGeneration,
         TestModelTagsHelperWithoutObject
-        ])
+        ]))
     for testsuite in suite:
         unittest.TextTestRunner(verbosity=1).run(testsuite)

File tests/test_paginate.py

 
 def test_one_page():
     """Test that we fit 10 items on a single 10-item page."""
-    items = range(10)
+    items = list(range(10))
     page = paginate.Page(items, page=0, items_per_page=10)
     assert page.page == 1
     assert page.first_item == 1
 
 def test_many_pages():
     """Test that 100 items fit on seven 15-item pages."""
-    items = range(100)
+    items = list(range(100))
     page = paginate.Page(items, page=0, items_per_page=15, url=url_generator)
+    print(page)
     eq_(page.page, 1)
     eq_(page.first_item, 1)
     eq_(page.last_item, 15)

File tests/test_tags.py

     def test_check_box(self):
         eq_(
             checkbox("admin"),
-            u'<input id="admin" name="admin" type="checkbox" value="1" />',
+            '<input id="admin" name="admin" type="checkbox" value="1" />',
         )
 
     def test_form(self):
         eq_(
             form(url="http://www.example.com"),
-            u'<form action="http://www.example.com" method="post">'
+            '<form action="http://www.example.com" method="post">'
         )
         eq_(
             form(url="http://www.example.com", method='GET'),
-            u'<form action="http://www.example.com" method="GET">'
+            '<form action="http://www.example.com" method="GET">'
         )
         eq_(
             form('/test/edit/1'),
-            u'<form action="/test/edit/1" method="post">'
+            '<form action="/test/edit/1" method="post">'
         )
 
     def test_form_multipart(self):
         eq_(
             form(url='http://www.example.com', multipart=True),
-            u'<form action="http://www.example.com" enctype="multipart/form-data" method="post">'
+            '<form action="http://www.example.com" enctype="multipart/form-data" method="post">'
         )
         
     def test_hidden_field(self):
         eq_(
             hidden("id", 3),
-            u'<input id="id" name="id" type="hidden" value="3" />'
+            '<input id="id" name="id" type="hidden" value="3" />'
         )
 
     def test_hidden_field_alt(self):
         eq_(
             hidden("id", '3'),
-            u'<input id="id" name="id" type="hidden" value="3" />'
+            '<input id="id" name="id" type="hidden" value="3" />'
         )
 
     def test_password_field(self):
         eq_(
             password("password"), 
-            u'<input id="password" name="password" type="password" />'
+            '<input id="password" name="password" type="password" />'
         )
 
     def test_radio_button(self):
         eq_(
             radio("people", "justin"),
-            u'<input id="people_justin" name="people" type="radio" value="justin" />'
+            '<input id="people_justin" name="people" type="radio" value="justin" />'
         )
         
         eq_(
             radio("num_people", 5),
-            u'<input id="num_people_5" name="num_people" type="radio" value="5" />'
+            '<input id="num_people_5" name="num_people" type="radio" value="5" />'
         )
 
         eq_(
             radio("num_people", 5),
-            u'<input id="num_people_5" name="num_people" type="radio" value="5" />'
+            '<input id="num_people_5" name="num_people" type="radio" value="5" />'
         )
         
         eq_(
             radio("gender", "m") + radio("gender", "f"),
-            u'<input id="gender_m" name="gender" type="radio" value="m" /><input id="gender_f" name="gender" type="radio" value="f" />'
+            '<input id="gender_m" name="gender" type="radio" value="m" /><input id="gender_f" name="gender" type="radio" value="f" />'
         )
         
         eq_(
             radio("opinion", "-1") + radio("opinion", "1"),
-            u'<input id="opinion_-1" name="opinion" type="radio" value="-1" /><input id="opinion_1" name="opinion" type="radio" value="1" />'
+            '<input id="opinion_-1" name="opinion" type="radio" value="-1" /><input id="opinion_1" name="opinion" type="radio" value="1" />'
         )
 
         eq_(
             radio("num_people", 5, checked=True),
-            u'<input checked="checked" id="num_people_5" name="num_people" type="radio" value="5" />'
+            '<input checked="checked" id="num_people_5" name="num_people" type="radio" value="5" />'
         )
 
     def test_submit(self):
         eq_(
-            u'<input id="commit" name="commit" type="submit" value="Save changes" />',
+            '<input id="commit" name="commit" type="submit" value="Save changes" />',
             submit("commit", "Save changes")
         )
 
     def test_text_area(self):
         eq_(
             textarea("aa", ""),
-            u'<textarea id="aa" name="aa"></textarea>'
+            '<textarea id="aa" name="aa"></textarea>'
         )
         eq_(
             textarea("aa", None),
-            u'<textarea id="aa" name="aa"></textarea>'
+            '<textarea id="aa" name="aa"></textarea>'
         )
         eq_(
             textarea("aa", "Hello!"),
-            u'<textarea id="aa" name="aa">Hello!</textarea>'
+            '<textarea id="aa" name="aa">Hello!</textarea>'
         )
 
     def test_text_area_size_string(self):
         eq_(
             textarea("body", "hello world", cols=20, rows=40),
-            u'<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>'
+            '<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>'
         )
 
     def test_text_field(self):
         eq_(
             text("title", ""),
-            u'<input id="title" name="title" type="text" value="" />'
+            '<input id="title" name="title" type="text" value="" />'
         )
         eq_(
             text("title", None),
-            u'<input id="title" name="title" type="text" />'
+            '<input id="title" name="title" type="text" />'
         )
         eq_(
             text("title", "Hello!"),
-            u'<input id="title" name="title" type="text" value="Hello!" />'
+            '<input id="title" name="title" type="text" value="Hello!" />'
         )
 
     def test_text_field_class_string(self):
         eq_(
             text( "title", "Hello!", class_= "admin"),
-            u'<input class="admin" id="title" name="title" type="text" value="Hello!" />'
+            '<input class="admin" id="title" name="title" type="text" value="Hello!" />'
         )
 
     def test_boolean_options(self):
         eq_(     
             checkbox("admin", 1, True, disabled = True, readonly="yes"),
-            u'<input checked="checked" disabled="disabled" id="admin" name="admin" readonly="readonly" type="checkbox" value="1" />'
+            '<input checked="checked" disabled="disabled" id="admin" name="admin" readonly="readonly" type="checkbox" value="1" />'
         )
         eq_(
             checkbox("admin", 1, True, disabled = False, readonly = None),
-            u'<input checked="checked" id="admin" name="admin" type="checkbox" value="1" />'
+            '<input checked="checked" id="admin" name="admin" type="checkbox" value="1" />'
         )
 
     def test_multiple_id_bug(self):
         # Don't set multiple id attributes for 'id_' argument.
         eq_(
             text("spam", "pizza", id="eggs"),
-            u'<input id="eggs" name="spam" type="text" value="pizza" />')
+            '<input id="eggs" name="spam" type="text" value="pizza" />')
         eq_(
             text("spam", "pizza", id_="eggs"), 
-            u'<input id="eggs" name="spam" type="text" value="pizza" />')
+            '<input id="eggs" name="spam" type="text" value="pizza" />')
         eq_(
             select("spam", [1,2], [2], id="eggs"),
-            u'<select id="eggs" name="spam">\n<option selected="selected" value="2">2</option>\n</select>')
+            '<select id="eggs" name="spam">\n<option selected="selected" value="2">2</option>\n</select>')
         eq_(
             select("spam", [1,2], [2], id_="eggs"),
-            u'<select id="eggs" name="spam">\n<option selected="selected" value="2">2</option>\n</select>')
+            '<select id="eggs" name="spam">\n<option selected="selected" value="2">2</option>\n</select>')
 
     def test_id_and_id_(self):
         raises(TypeError, text, "spam", "pizza", id="fubar", id_="eggs")
     
 class TestLinkHelper(object):
     def test_link_tag_with_query(self):
-        eq_(u"<a href=\"http://www.example.com?q1=v1&amp;q2=v2\">Hello</a>", 
+        eq_("<a href=\"http://www.example.com?q1=v1&amp;q2=v2\">Hello</a>", 
                link_to("Hello", "http://www.example.com?q1=v1&q2=v2"))
     
     def test_link_tag_with_query_and_no_name(self):
-        eq_(u"<a href=\"http://www.example.com?q1=v1&amp;q2=v2\">http://www.example.com?q1=v1&amp;q2=v2</a>", 
+        eq_("<a href=\"http://www.example.com?q1=v1&amp;q2=v2\">http://www.example.com?q1=v1&amp;q2=v2</a>", 
                link_to(None, HTML.literal("http://www.example.com?q1=v1&amp;q2=v2")))
     
     def test_link_tag_with_custom_onclick(self):
-        eq_(u"<a href=\"http://www.example.com\" onclick=\"alert(&#39;yay!&#39;)\">Hello</a>", 
+        eq_("<a href=\"http://www.example.com\" onclick=\"alert(&#39;yay!&#39;)\">Hello</a>", 
                link_to("Hello", "http://www.example.com", onclick="alert('yay!')"))
     
 
 class TestAssetTagHelper(object):
     def test_auto_discovery_link_tag(self):
-        eq_(literal(u'<link href="http://feed.com/feed.xml" rel="alternate" title="RSS" type="application/rss+xml" />'),
+        eq_(literal('<link href="http://feed.com/feed.xml" rel="alternate" title="RSS" type="application/rss+xml" />'),
                          auto_discovery_link('http://feed.com/feed.xml'))
         eq_('<link href="http://feed.com/feed.xml" rel="alternate" title="ATOM" type="application/atom+xml" />',
                          auto_discovery_link('http://feed.com/feed.xml', feed_type='atom'))
                          javascript_link('/js/pngfix.js', defer=True))
 
     def test_stylesheet_link_tag(self):
-        eq_(literal(u'<link href="/dir/file.css" media="all" rel="stylesheet" type="text/css" />'),
+        eq_(literal('<link href="/dir/file.css" media="all" rel="stylesheet" type="text/css" />'),
                          stylesheet_link('/dir/file.css', media='all'))
         eq_('<link href="style.css" media="all" rel="stylesheet" type="text/css" />',
                          stylesheet_link('style.css', media='all'))

File tests/test_text.py

                          excerpt('This is a beautiful? morning', 'beautiful', 5))
 
     def test_excerpt_with_utf8(self):
-        self.assertEqual(u"...fficiency could not be ...",
-                         excerpt(u"That's why efficiency could not be helped", 'could', 8))
+        self.assertEqual("...fficiency could not be ...",
+                         excerpt("That's why efficiency could not be helped", 'could', 8))
 
 
     def test_truncate(self):

File tests/test_tools.py

             }
 
         result_values = {}
-        for k, v in result_values_templates.iteritems():
+        for k, v in list(result_values_templates.items()):
             result_values[k] = Template(v).substitute(raw_values)
 
         self.assertEqual(result_values["email_result"], auto_link(raw_values['email_raw'], 'email_addresses'))
-        self.assertEqual(u"hello %(email_result)s" % result_values, auto_link("hello %(email_raw)s" % raw_values, 'email_addresses'))
-        self.assertEqual(u"Go to %(link_result)s" % result_values, auto_link("Go to %(link_raw)s" % raw_values, 'urls'))
-        self.assertEqual(u"Go to %(link_raw)s" % raw_values, auto_link("Go to %(link_raw)s" % raw_values, 'email_addresses'))
-        self.assertEqual(u"Go to %(link_result)s and say hello to %(email_result)s" % result_values, auto_link("Go to %(link_raw)s and say hello to %(email_raw)s" % raw_values))
-        self.assertEqual(u"<p>Link %(link_result)s</p>" % result_values, auto_link(literal("<p>Link %(link_raw)s</p>") % raw_values))
-        self.assertEqual(u"<p>%(link_result)s Link</p>" % result_values, auto_link(literal("<p>%(link_raw)s Link</p>") % raw_values))
-        self.assertEqual(u"<p>Link %(link_result_with_options)s</p>" % result_values, auto_link(literal("<p>Link %(link_raw)s</p>") % raw_values, 'all', target='_blank'))
-        self.assertEqual(u"Go to %(link_result)s." % result_values, auto_link("Go to %(link_raw)s." % raw_values))
-        self.assertEqual(u"<p>Go to %(link_result)s, then say hello to %(email_result)s.</p>" % result_values, auto_link(literal("<p>Go to %(link_raw)s, then say hello to %(email_raw)s.</p>") % raw_values))
-        self.assertEqual(u"Go to %(link2_result)s" % result_values, auto_link("Go to %(link2_raw)s" % raw_values, 'urls'))
-        self.assertEqual(u"Go to %(link2_raw)s" % raw_values, auto_link("Go to %(link2_raw)s" % raw_values, 'email_addresses'))
-        self.assertEqual(u"<p>Link %(link2_result)s</p>" % result_values, auto_link(literal("<p>Link %(link2_raw)s</p>") % raw_values))
-        self.assertEqual(u"<p>%(link2_result)s Link</p>" % result_values, auto_link(literal("<p>%(link2_raw)s Link</p>") % raw_values))
-        self.assertEqual(u"Go to %(link2_result)s." % result_values, auto_link(literal("Go to %(link2_raw)s.") % raw_values))
-        self.assertEqual(u"<p>Say hello to %(email_result)s, then go to %(link2_result)s.</p>" % result_values, auto_link(literal("<p>Say hello to %(email_raw)s, then go to %(link2_raw)s.</p>") % raw_values))
-        self.assertEqual(u"Go to %(link3_result)s" % result_values, auto_link("Go to %(link3_raw)s" % raw_values, 'urls'))
-        self.assertEqual(u"Go to %(link3_raw)s" % raw_values, auto_link("Go to %(link3_raw)s" % raw_values, 'email_addresses'))
-        self.assertEqual(u"<p>Link %(link3_result)s</p>" % result_values, auto_link(literal("<p>Link %(link3_raw)s</p>") % raw_values))
-        self.assertEqual(u"<p>%(link3_result)s Link</p>" % result_values, auto_link(literal("<p>%(link3_raw)s Link</p>") % raw_values))
-        self.assertEqual(u"Go to %(link3_result)s." % result_values, auto_link("Go to %(link3_raw)s." % raw_values))
-        self.assertEqual(u"<p>Go to %(link3_result)s. seriously, %(link3_result)s? i think I'll say hello to %(email_result)s. instead.</p>" % result_values, auto_link(literal("<p>Go to %(link3_raw)s. seriously, %(link3_raw)s? i think I'll say hello to %(email_raw)s. instead.</p>") % raw_values))
-        self.assertEqual(u"<p>Link %(link4_result)s</p>" % result_values, auto_link(literal("<p>Link %(link4_raw)s</p>") % raw_values))
-        self.assertEqual(u"<p>%(link4_result)s Link</p>" % result_values, auto_link(literal("<p>%(link4_raw)s Link</p>") % raw_values))
-        self.assertEqual(u"<p>%(link5_result)s Link</p>" % result_values, auto_link(literal("<p>%(link5_raw)s Link</p>") % raw_values))
-        self.assertEqual(u"<p>%(link6_result)s Link</p>" % result_values, auto_link(literal("<p>%(link6_raw)s Link</p>") % raw_values))
-        self.assertEqual(u"<p>%(link7_result)s Link</p>" % result_values, auto_link(literal("<p>%(link7_raw)s Link</p>") % raw_values))
-        self.assertEqual(u"Go to %(link8_result)s" % result_values, auto_link("Go to %(link8_raw)s" % raw_values, 'urls'))
-        self.assertEqual(u"Go to %(link8_raw)s" % raw_values, auto_link("Go to %(link8_raw)s" % raw_values, 'email_addresses'))
-        self.assertEqual(u"<p>Link %(link8_result)s</p>" % result_values, auto_link(literal("<p>Link %(link8_raw)s</p>") % raw_values))
-        self.assertEqual(u"<p>%(link8_result)s Link</p>" % result_values, auto_link(literal("<p>%(link8_raw)s Link</p>") % raw_values))
-        self.assertEqual(u"Go to %(link8_result)s." % result_values, auto_link("Go to %(link8_raw)s." % raw_values))
-        self.assertEqual(u"<p>Go to %(link8_result)s. seriously, %(link8_result)s? i think I'll say hello to %(email_result)s. instead.</p>" % result_values, auto_link(literal("<p>Go to %(link8_raw)s. seriously, %(link8_raw)s? i think I'll say hello to %(email_raw)s. instead.</p>") % raw_values))
-        self.assertEqual(u"Go to %(link9_result)s" % result_values, auto_link("Go to %(link9_raw)s" % raw_values, 'urls'))
-        self.assertEqual(u"Go to %(link9_raw)s" % raw_values, auto_link("Go to %(link9_raw)s" % raw_values, 'email_addresses'))
-        self.assertEqual(u"<p>Link %(link9_result)s</p>" % result_values, auto_link(literal("<p>Link %(link9_raw)s</p>") % raw_values))
-        self.assertEqual(u"<p>%(link9_result)s Link</p>" % result_values, auto_link(literal("<p>%(link9_raw)s Link</p>") % raw_values))
-        self.assertEqual(u"Go to %(link9_result)s." % result_values, auto_link("Go to %(link9_raw)s." % raw_values))
-        self.assertEqual(u"<p>Go to %(link9_result)s. seriously, %(link9_result)s? i think I'll say hello to %(email_result)s. instead.</p>" % result_values, auto_link(literal("<p>Go to %(link9_raw)s. seriously, %(link9_raw)s? i think I'll say hello to %(email_raw)s. instead.</p>") % raw_values))
-        self.assertEqual(u"", auto_link(None))
-        self.assertEqual(u"", auto_link(""))
+        self.assertEqual("hello %(email_result)s" % result_values, auto_link("hello %(email_raw)s" % raw_values, 'email_addresses'))
+        self.assertEqual("Go to %(link_result)s" % result_values, auto_link("Go to %(link_raw)s" % raw_values, 'urls'))
+        self.assertEqual("Go to %(link_raw)s" % raw_values, auto_link("Go to %(link_raw)s" % raw_values, 'email_addresses'))
+        self.assertEqual("Go to %(link_result)s and say hello to %(email_result)s" % result_values, auto_link("Go to %(link_raw)s and say hello to %(email_raw)s" % raw_values))
+        self.assertEqual("<p>Link %(link_result)s</p>" % result_values, auto_link(literal("<p>Link %(link_raw)s</p>") % raw_values))
+        self.assertEqual("<p>%(link_result)s Link</p>" % result_values, auto_link(literal("<p>%(link_raw)s Link</p>") % raw_values))
+        self.assertEqual("<p>Link %(link_result_with_options)s</p>" % result_values, auto_link(literal("<p>Link %(link_raw)s</p>") % raw_values, 'all', target='_blank'))
+        self.assertEqual("Go to %(link_result)s." % result_values, auto_link("Go to %(link_raw)s." % raw_values))
+        self.assertEqual("<p>Go to %(link_result)s, then say hello to %(email_result)s.</p>" % result_values, auto_link(literal("<p>Go to %(link_raw)s, then say hello to %(email_raw)s.</p>") % raw_values))
+        self.assertEqual("Go to %(link2_result)s" % result_values, auto_link("Go to %(link2_raw)s" % raw_values, 'urls'))
+        self.assertEqual("Go to %(link2_raw)s" % raw_values, auto_link("Go to %(link2_raw)s" % raw_values, 'email_addresses'))
+        self.assertEqual("<p>Link %(link2_result)s</p>" % result_values, auto_link(literal("<p>Link %(link2_raw)s</p>") % raw_values))
+        self.assertEqual("<p>%(link2_result)s Link</p>" % result_values, auto_link(literal("<p>%(link2_raw)s Link</p>") % raw_values))
+        self.assertEqual("Go to %(link2_result)s." % result_values, auto_link(literal("Go to %(link2_raw)s.") % raw_values))
+        self.assertEqual("<p>Say hello to %(email_result)s, then go to %(link2_result)s.</p>" % result_values, auto_link(literal("<p>Say hello to %(email_raw)s, then go to %(link2_raw)s.</p>") % raw_values))
+        self.assertEqual("Go to %(link3_result)s" % result_values, auto_link("Go to %(link3_raw)s" % raw_values, 'urls'))
+        self.assertEqual("Go to %(link3_raw)s" % raw_values, auto_link("Go to %(link3_raw)s" % raw_values, 'email_addresses'))
+        self.assertEqual("<p>Link %(link3_result)s</p>" % result_values, auto_link(literal("<p>Link %(link3_raw)s</p>") % raw_values))
+        self.assertEqual("<p>%(link3_result)s Link</p>" % result_values, auto_link(literal("<p>%(link3_raw)s Link</p>") % raw_values))
+        self.assertEqual("Go to %(link3_result)s." % result_values, auto_link("Go to %(link3_raw)s." % raw_values))
+        self.assertEqual("<p>Go to %(link3_result)s. seriously, %(link3_result)s? i think I'll say hello to %(email_result)s. instead.</p>" % result_values, auto_link(literal("<p>Go to %(link3_raw)s. seriously, %(link3_raw)s? i think I'll say hello to %(email_raw)s. instead.</p>") % raw_values))
+        self.assertEqual("<p>Link %(link4_result)s</p>" % result_values, auto_link(literal("<p>Link %(link4_raw)s</p>") % raw_values))
+        self.assertEqual("<p>%(link4_result)s Link</p>" % result_values, auto_link(literal("<p>%(link4_raw)s Link</p>") % raw_values))
+        self.assertEqual("<p>%(link5_result)s Link</p>" % result_values, auto_link(literal("<p>%(link5_raw)s Link</p>") % raw_values))
+        self.assertEqual("<p>%(link6_result)s Link</p>" % result_values, auto_link(literal("<p>%(link6_raw)s Link</p>") % raw_values))
+        self.assertEqual("<p>%(link7_result)s Link</p>" % result_values, auto_link(literal("<p>%(link7_raw)s Link</p>") % raw_values))
+        self.assertEqual("Go to %(link8_result)s" % result_values, auto_link("Go to %(link8_raw)s" % raw_values, 'urls'))
+        self.assertEqual("Go to %(link8_raw)s" % raw_values, auto_link("Go to %(link8_raw)s" % raw_values, 'email_addresses'))
+        self.assertEqual("<p>Link %(link8_result)s</p>" % result_values, auto_link(literal("<p>Link %(link8_raw)s</p>") % raw_values))
+        self.assertEqual("<p>%(link8_result)s Link</p>" % result_values, auto_link(literal("<p>%(link8_raw)s Link</p>") % raw_values))
+        self.assertEqual("Go to %(link8_result)s." % result_values, auto_link("Go to %(link8_raw)s." % raw_values))
+        self.assertEqual("<p>Go to %(link8_result)s. seriously, %(link8_result)s? i think I'll say hello to %(email_result)s. instead.</p>" % result_values, auto_link(literal("<p>Go to %(link8_raw)s. seriously, %(link8_raw)s? i think I'll say hello to %(email_raw)s. instead.</p>") % raw_values))
+        self.assertEqual("Go to %(link9_result)s" % result_values, auto_link("Go to %(link9_raw)s" % raw_values, 'urls'))
+        self.assertEqual("Go to %(link9_raw)s" % raw_values, auto_link("Go to %(link9_raw)s" % raw_values, 'email_addresses'))
+        self.assertEqual("<p>Link %(link9_result)s</p>" % result_values, auto_link(literal("<p>Link %(link9_raw)s</p>") % raw_values))
+        self.assertEqual("<p>%(link9_result)s Link</p>" % result_values, auto_link(literal("<p>%(link9_raw)s Link</p>") % raw_values))
+        self.assertEqual("Go to %(link9_result)s." % result_values, auto_link("Go to %(link9_raw)s." % raw_values))
+        self.assertEqual("<p>Go to %(link9_result)s. seriously, %(link9_result)s? i think I'll say hello to %(email_result)s. instead.</p>" % result_values, auto_link(literal("<p>Go to %(link9_raw)s. seriously, %(link9_raw)s? i think I'll say hello to %(email_raw)s. instead.</p>") % raw_values))
+        self.assertEqual("", auto_link(None))
+        self.assertEqual("", auto_link(""))
         # Failing test: PylonsHQ bug #657
         #self.assertEqual(u'&lt;<a href="http://www.google.com">www.google.com</a>&gt;', auto_link("<www.google.com>"))
 
 
 class TestURLHelper(WebHelpersTestCase):
     def test_button_to_with_straight_url(self):
-        self.assertEqual(u"<form action=\"http://www.example.com\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", 
+        self.assertEqual("<form action=\"http://www.example.com\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", 
                button_to("Hello", "http://www.example.com"))
 
     def test_button_to_with_query(self):
-        self.assertEqual(u"<form action=\"http://www.example.com/q1=v1&amp;q2=v2\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", 
+        self.assertEqual("<form action=\"http://www.example.com/q1=v1&amp;q2=v2\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", 
                button_to("Hello", "http://www.example.com/q1=v1&q2=v2"))
 
     def test_button_to_with_escaped_query(self):
-        self.assertEqual(u"<form action=\"http://www.example.com/q1=v1&amp;q2=v2\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"Hello\" /></div></form>",
+        self.assertEqual("<form action=\"http://www.example.com/q1=v1&amp;q2=v2\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"Hello\" /></div></form>",
                          button_to("Hello", "http://www.example.com/q1=v1&q2=v2"))
     
     def test_button_to_with_query_and_no_name(self):
-        self.assertEqual(u"<form action=\"http://www.example.com?q1=v1&amp;q2=v2\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"http://www.example.com?q1=v1&amp;q2=v2\" /></div></form>", 
+        self.assertEqual("<form action=\"http://www.example.com?q1=v1&amp;q2=v2\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"http://www.example.com?q1=v1&amp;q2=v2\" /></div></form>", 
                button_to(None, "http://www.example.com?q1=v1&q2=v2"))
     
     def test_button_to_enabled_disabled(self):
-        self.assertEqual(u"<form action=\"http://www.example.com\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"Hello\" /></div></form>",
+        self.assertEqual("<form action=\"http://www.example.com\" class=\"button-to\" method=\"POST\"><div><input type=\"submit\" value=\"Hello\" /></div></form>",
                button_to("Hello", "http://www.example.com", disabled=False))
-        self.assertEqual(u"<form action=\"http://www.example.com\" class=\"button-to\" method=\"POST\"><div><input disabled=\"disabled\" type=\"submit\" value=\"Hello\" /></div></form>",
+        self.assertEqual("<form action=\"http://www.example.com\" class=\"button-to\" method=\"POST\"><div><input disabled=\"disabled\" type=\"submit\" value=\"Hello\" /></div></form>",
                button_to("Hello", "http://www.example.com", disabled=True))
     
     def test_button_to_with_method_delete(self):
-        self.assertEqual(u"<form action=\"http://www.example.com\" class=\"button-to\" method=\"POST\"><div><input id=\"_method\" name=\"_method\" type=\"hidden\" value=\"DELETE\" /><input type=\"submit\" value=\"Hello\" /></div></form>", 
+        self.assertEqual("<form action=\"http://www.example.com\" class=\"button-to\" method=\"POST\"><div><input id=\"_method\" name=\"_method\" type=\"hidden\" value=\"DELETE\" /><input type=\"submit\" value=\"Hello\" /></div></form>", 
             button_to("Hello", "http://www.example.com", method='DELETE'))
-        self.assertEqual(u"<form action=\"http://www.example.com\" class=\"button-to\" method=\"post\"><div><input id=\"_method\" name=\"_method\" type=\"hidden\" value=\"delete\" /><input type=\"submit\" value=\"Hello\" /></div></form>", 
+        self.assertEqual("<form action=\"http://www.example.com\" class=\"button-to\" method=\"post\"><div><input id=\"_method\" name=\"_method\" type=\"hidden\" value=\"delete\" /><input type=\"submit\" value=\"Hello\" /></div></form>", 
             button_to("Hello", "http://www.example.com", method='delete'))
 
     def test_button_to_with_method_get(self):
-        self.assertEqual(u"<form action=\"http://www.example.com\" class=\"button-to\" method=\"get\"><div><input type=\"submit\" value=\"Hello\" /></div></form>",
+        self.assertEqual("<form action=\"http://www.example.com\" class=\"button-to\" method=\"get\"><div><input type=\"submit\" value=\"Hello\" /></div></form>",
             button_to("Hello", "http://www.example.com", method='get'))
-        self.assertEqual(u"<form action=\"http://www.example.com\" class=\"button-to\" method=\"GET\"><div><input type=\"submit\" value=\"Hello\" /></div></form>",
+        self.assertEqual("<form action=\"http://www.example.com\" class=\"button-to\" method=\"GET\"><div><input type=\"submit\" value=\"Hello\" /></div></form>",
             button_to("Hello", "http://www.example.com", method='GET'))
 
     def test_button_to_with_img(self):
-        self.assertEqual(u'<form action="/content/edit/3" class="button-to" method="POST"><div><input alt="Edit" src="/images/icon_delete.gif" type="image" value="Edit" /></div></form>',
+        self.assertEqual('<form action="/content/edit/3" class="button-to" method="POST"><div><input alt="Edit" src="/images/icon_delete.gif" type="image" value="Edit" /></div></form>',
                          button_to("Edit", '/content/edit/3', type='image', src='/images/icon_delete.gif'))
-        self.assertEqual(u'<form action="/content/submit/3" class="button-to" method="POST"><div><input alt="Complete the form" src="submit.png" type="image" value="Submit" /></div></form>',
+        self.assertEqual('<form action="/content/submit/3" class="button-to" method="POST"><div><input alt="Complete the form" src="submit.png" type="image" value="Submit" /></div></form>',
                          button_to("Submit", '/content/submit/3', type='image', src='submit.png', alt='Complete the form'))
 
     def test_mail_to(self):
-        self.assertEqual(u'<a href="mailto:justin@example.com">justin@example.com</a>', mail_to("justin@example.com"))
-        self.assertEqual(u'<a href="mailto:justin@example.com">Justin Example</a>', mail_to("justin@example.com", "Justin Example"))
-        self.assertEqual(u'<a class="admin" href="mailto:justin@example.com">Justin Example</a>',
+        self.assertEqual('<a href="mailto:justin@example.com">justin@example.com</a>', mail_to("justin@example.com"))
+        self.assertEqual('<a href="mailto:justin@example.com">Justin Example</a>', mail_to("justin@example.com", "Justin Example"))
+        self.assertEqual('<a class="admin" href="mailto:justin@example.com">Justin Example</a>',
                          mail_to("justin@example.com", "Justin Example", class_="admin"))
 
     def test_mail_to_with_javascript(self):
-        self.assertEqual(u"<script type=\"text/javascript\">\n//<![CDATA[\neval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))\n//]]>\n</script>", mail_to("me@domain.com", "My email", encode = "javascript"))
+        self.assertEqual("<script type=\"text/javascript\">\n//<![CDATA[\neval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))\n//]]>\n</script>", mail_to("me@domain.com", "My email", encode = "javascript"))
 
     def test_mail_to_with_options(self):
-        self.assertEqual(u'<a href="mailto:me@example.com?cc=ccaddress%40example.com&amp;bcc=bccaddress%40example.com&amp;subject=This%20is%20an%20example%20email&amp;body=This%20is%20the%20body%20of%20the%20message.">My email</a>',
+        self.assertEqual('<a href="mailto:me@example.com?cc=ccaddress%40example.com&amp;bcc=bccaddress%40example.com&amp;subject=This%20is%20an%20example%20email&amp;body=This%20is%20the%20body%20of%20the%20message.">My email</a>',
             mail_to("me@example.com", "My email", cc="ccaddress@example.com",
                     bcc="bccaddress@example.com", subject="This is an example email",
                     body="This is the body of the message."))
 
     def test_mail_to_with_img(self):
-        self.assertEqual(u'<a href="mailto:feedback@example.com"><img src="/feedback.png" /></a>',
+        self.assertEqual('<a href="mailto:feedback@example.com"><img src="/feedback.png" /></a>',
                         mail_to('feedback@example.com', HTML.literal('<img src="/feedback.png" />')))
 
     def test_mail_to_with_hex(self):
-        self.assertEqual(u"<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>",
+        self.assertEqual("<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>",
                          mail_to("me@domain.com", "My email", encode = "hex"))
-        self.assertEqual(u"<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">&#109;&#101;&#64;&#100;&#111;&#109;&#97;&#105;&#110;&#46;&#99;&#111;&#109;</a>",
+        self.assertEqual("<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">&#109;&#101;&#64;&#100;&#111;&#109;&#97;&#105;&#110;&#46;&#99;&#111;&#109;</a>",
                          mail_to("me@domain.com", None, encode = "hex"))
 
     def test_mail_to_with_replace_options(self):
-        self.assertEqual(u'<a href="mailto:wolfgang@stufenlos.net">wolfgang(at)stufenlos(dot)net</a>',
+        self.assertEqual('<a href="mailto:wolfgang@stufenlos.net">wolfgang(at)stufenlos(dot)net</a>',
                         mail_to("wolfgang@stufenlos.net", None, replace_at="(at)", replace_dot="(dot)"))
-        self.assertEqual(u"<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">&#109;&#101;&#40;&#97;&#116;&#41;&#100;&#111;&#109;&#97;&#105;&#110;&#46;&#99;&#111;&#109;</a>",
+        self.assertEqual("<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">&#109;&#101;&#40;&#97;&#116;&#41;&#100;&#111;&#109;&#97;&#105;&#110;&#46;&#99;&#111;&#109;</a>",
                          mail_to("me@domain.com", None, encode = "hex", replace_at = "(at)"))
-        self.assertEqual(u"<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>",
+        self.assertEqual("<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>",
                          mail_to("me@domain.com", "My email", encode = "hex", replace_at = "(at)"))
-        self.assertEqual(u"<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">&#109;&#101;&#40;&#97;&#116;&#41;&#100;&#111;&#109;&#97;&#105;&#110;&#40;&#100;&#111;&#116;&#41;&#99;&#111;&#109;</a>",
+        self.assertEqual("<a href=\"&#109;&#97;&#105;&#108;&#116;&#111;&#58;%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">&#109;&#101;&#40;&#97;&#116;&#41;&#100;&#111;&#109;&#97;&#105;&#110;&#40;&#100;&#111;&#116;&#41;&#99;&#111;&#109;</a>",
                          mail_to("me@domain.com", None, encode = "hex", replace_at = "(at)", replace_dot = "(dot)"))
-        self.assertEqual(u"<script type=\"text/javascript\">\n//<![CDATA[\neval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))\n//]]>\n</script>",
+        self.assertEqual("<script type=\"text/javascript\">\n//<![CDATA[\neval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))\n//]]>\n</script>",
                          mail_to("me@domain.com", "My email", encode = "javascript", replace_at = "(at)", replace_dot = "(dot)"))
 
 
                 style="color:red"))
 
     def test_highlight_literal(self):
-        eq_(literal(u'The &lt;red&gt; c<strong class="highlight">at</strong>.'),
+        eq_(literal('The &lt;red&gt; c<strong class="highlight">at</strong>.'),
             highlight("The <red> cat.", "at"))
-        eq_(literal(u'The <red> c<strong class="highlight">at</strong>.'),
+        eq_(literal('The <red> c<strong class="highlight">at</strong>.'),
             highlight(literal("The <red> cat."), "at"))
 
     def test_highlight_legacy_highlighter(self):
 
 class TestStripTagsHelper(WebHelpersTestCase):
     def test_compare_strip_tags_to_sanitize(self):
-        text = u'I <i>really</i> like <script language="javascript">NEFARIOUS CODE</script> steak!'
+        text = 'I <i>really</i> like <script language="javascript">NEFARIOUS CODE</script> steak!'
         eq_(strip_tags(text), render.sanitize(text))
 
 if __name__ == '__main__':
-    suite = map(unittest.makeSuite, [
+    suite = list(map(unittest.makeSuite, [
         TestToolsHelper,
         TestHighlightHelper,
         TestURLHelper,
         TestStripTagsHelper,
-        ])
+        ]))
     for testsuite in suite:
         unittest.TextTestRunner(verbosity=1).run(testsuite)

File webhelpers/feedgenerator.py

     if date is not None:
         tag = re.sub('/', ',%s:/' % date.strftime('%Y-%m-%d'), tag, 1)
     tag = re.sub('#', '/', tag)
-    return u'tag:' + tag
+    return 'tag:' + tag
 
 class SyndicationFeed(object):
     "Base class for all syndication feeds. Subclasses should provide write()"
         """
         Returns the feed in the given encoding as a string.
         """
-        from StringIO import StringIO
+        from io import StringIO
         s = StringIO()
         self.write(s, encoding)
         return s.getvalue()
 
 class RssFeed(SyndicationFeed):
     mime_type = 'application/rss+xml'
-    _version = u"?"
+    _version = "?"
     def write(self, outfile, encoding):
         handler = SimplerXMLGenerator(outfile, encoding)
         handler.startDocument()
-        handler.startElement(u"rss", self.rss_attributes())
-        handler.startElement(u"channel", self.root_attributes())
+        handler.startElement("rss", self.rss_attributes())
+        handler.startElement("channel", self.root_attributes())
         self.add_root_elements(handler)
         self.write_items(handler)
         self.endChannelElement(handler)
-        handler.endElement(u"rss")
+        handler.endElement("rss")
 
     def rss_attributes(self):
-        return {u"version": self._version}
+        return {"version": self._version}
 
     def write_items(self, handler):
         for item in self.items:
-            handler.startElement(u'item', self.item_attributes(item))
+            handler.startElement('item', self.item_attributes(item))
             self.add_item_elements(handler, item)
-            handler.endElement(u"item")
+            handler.endElement("item")
 
     def add_root_elements(self, handler):
-        handler.addQuickElement(u"title", self.feed['title'])
-        handler.addQuickElement(u"link", self.feed['link'])
-        handler.addQuickElement(u"description", self.feed['description'])
+        handler.addQuickElement("title", self.feed['title'])
+        handler.addQuickElement("link", self.feed['link'])
+        handler.addQuickElement("description", self.feed['description'])
         if self.feed['language'] is not None:
-            handler.addQuickElement(u"language", self.feed['language'])
+            handler.addQuickElement("language", self.feed['language'])
         for cat in self.feed['categories']:
-            handler.addQuickElement(u"category", cat)
+            handler.addQuickElement("category", cat)
         if self.feed['feed_copyright'] is not None:
-            handler.addQuickElement(u"copyright", self.feed['feed_copyright'])
-        handler.addQuickElement(u"lastBuildDate", rfc2822_date(self.latest_post_date()).decode('utf-8'))
+            handler.addQuickElement("copyright", self.feed['feed_copyright'])
+        handler.addQuickElement("lastBuildDate", rfc2822_date(self.latest_post_date()))
         if self.feed['ttl'] is not None:
-            handler.addQuickElement(u"ttl", self.feed['ttl'])
+            handler.addQuickElement("ttl", self.feed['ttl'])
 
     def endChannelElement(self, handler):
-        handler.endElement(u"channel")
+        handler.endElement("channel")
 
 class RssUserland091Feed(RssFeed):
-    _version = u"0.91"
+    _version = "0.91"
     def add_item_elements(self, handler, item):
-        handler.addQuickElement(u"title", item['title'])
-        handler.addQuickElement(u"link", item['link'])
+        handler.addQuickElement("title", item['title'])
+        handler.addQuickElement("link", item['link'])
         if item['description'] is not None:
-            handler.addQuickElement(u"description", item['description'])
+            handler.addQuickElement("description", item['description'])
 
 class Rss201rev2Feed(RssFeed):
     # Spec: http://blogs.law.harvard.edu/tech/rss
-    _version = u"2.0"
+    _version = "2.0"
     def add_item_elements(self, handler, item):
-        handler.addQuickElement(u"title", item['title'])
-        handler.addQuickElement(u"link", item['link'])
+        handler.addQuickElement("title", item['title'])
+        handler.addQuickElement("link", item['link'])
         if item['description'] is not None:
-            handler.addQuickElement(u"description", item['description'])
+            handler.addQuickElement("description", item['description'])
 
         # Author information.
         if item["author_name"] and item["author_email"]:
-            handler.addQuickElement(u"author", "%s (%s)" % \
+            handler.addQuickElement("author", "%s (%s)" % \
                 (item['author_email'], item['author_name']))
         elif item["author_email"]:
-            handler.addQuickElement(u"author", item["author_email"])
+            handler.addQuickElement("author", item["author_email"])
         elif item["author_name"]:
-            handler.addQuickElement(u"dc:creator", item["author_name"], {"xmlns:dc": u"http://purl.org/dc/elements/1.1/"})
+            handler.addQuickElement("dc:creator", item["author_name"], {"xmlns:dc": "http://purl.org/dc/elements/1.1/"})
 
         if item['pubdate'] is not None:
-            handler.addQuickElement(u"pubDate", rfc2822_date(item['pubdate']).decode('utf-8'))
+            handler.addQuickElement("pubDate", rfc2822_date(item['pubdate']))
         if item['comments'] is not None:
-            handler.addQuickElement(u"comments", item['comments'])
+            handler.addQuickElement("comments", item['comments'])
         if item['unique_id'] is not None:
-            handler.addQuickElement(u"guid", item['unique_id'])
+            handler.addQuickElement("guid", item['unique_id'])
         if item['ttl'] is not None:
-            handler.addQuickElement(u"ttl", item['ttl'])
+            handler.addQuickElement("ttl", item['ttl'])
 
         # Enclosure.
         if item['enclosure'] is not None:
-            handler.addQuickElement(u"enclosure", '',
-                {u"url": item['enclosure'].url, u"length": item['enclosure'].length,
-                    u"type": item['enclosure'].mime_type})
+            handler.addQuickElement("enclosure", '',
+                {"url": item['enclosure'].url, "length": item['enclosure'].length,
+                    "type": item['enclosure'].mime_type})
 
         # Categories.
         for cat in item['categories']:
-            handler.addQuickElement(u"category", cat)
+            handler.addQuickElement("category", cat)
 
 class Atom1Feed(SyndicationFeed):
     # Spec: http://atompub.org/2005/07/11/draft-ietf-atompub-format-10.html
     mime_type = 'application/atom+xml'
-    ns = u"http://www.w3.org/2005/Atom"
+    ns = "http://www.w3.org/2005/Atom"
 
     def write(self, outfile, encoding):
         handler = SimplerXMLGenerator(outfile, encoding)
         handler.startDocument()
-        handler.startElement(u'feed', self.root_attributes())
+        handler.startElement('feed', self.root_attributes())
         self.add_root_elements(handler)
         self.write_items(handler)
-        handler.endElement(u"feed")
+        handler.endElement("feed")
 
     def root_attributes(self):
         if self.feed['language'] is not None:
-            return {u"xmlns": self.ns, u"xml:lang": self.feed['language']}
+            return {"xmlns": self.ns, "xml:lang": self.feed['language']}
         else:
-            return {u"xmlns": self.ns}
+            return {"xmlns": self.ns}
 
     def add_root_elements(self, handler):
-        handler.addQuickElement(u"title", self.feed['title'])
-        handler.addQuickElement(u"link", "", {u"rel": u"alternate", u"href": self.feed['link']})
+        handler.addQuickElement("title", self.feed['title'])
+        handler.addQuickElement("link", "", {"rel": "alternate", "href": self.feed['link']})
         if self.feed['feed_url'] is not None:
-            handler.addQuickElement(u"link", "", {u"rel": u"self", u"href": self.feed['feed_url']})
-        handler.addQuickElement(u"id", self.feed['id'])
-        handler.addQuickElement(u"updated", rfc3339_date(self.latest_post_date()).decode('utf-8'))
+            handler.addQuickElement("link", "", {"rel": "self", "href": self.feed['feed_url']})
+        handler.addQuickElement("id", self.feed['id'])
+        handler.addQuickElement("updated", rfc3339_date(self.latest_post_date()))
         if self.feed['author_name'] is not None:
-            handler.startElement(u"author", {})
-            handler.addQuickElement(u"name", self.feed['author_name'])
+            handler.startElement("author", {})
+            handler.addQuickElement("name", self.feed['author_name'])
             if self.feed['author_email'] is not None:
-                handler.addQuickElement(u"email", self.feed['author_email'])
+                handler.addQuickElement("email", self.feed['author_email'])
             if self.feed['author_link'] is not None:
-                handler.addQuickElement(u"uri", self.feed['author_link'])
-            handler.endElement(u"author")
+                handler.addQuickElement("uri", self.feed['author_link'])
+            handler.endElement("author")
         if self.feed['subtitle'] is not None:
-            handler.addQuickElement(u"subtitle", self.feed['subtitle'])
+            handler.addQuickElement("subtitle", self.feed['subtitle'])
         for cat in self.feed['categories']:
-            handler.addQuickElement(u"category", "", {u"term": cat})
+            handler.addQuickElement("category", "", {"term": cat})
         if self.feed['feed_copyright'] is not None:
-            handler.addQuickElement(u"rights", self.feed['feed_copyright'])
+            handler.addQuickElement("rights", self.feed['feed_copyright'])
 
     def write_items(self, handler):
         for item in self.items:
-            handler.startElement(u"entry", self.item_attributes(item))
+            handler.startElement("entry", self.item_attributes(item))
             self.add_item_elements(handler, item)
-            handler.endElement(u"entry")
+            handler.endElement("entry")
 
     def add_item_elements(self, handler, item):
-        handler.addQuickElement(u"title", item['title'])
-        handler.addQuickElement(u"link", u"", {u"href": item['link'], u"rel": u"alternate"})
+        handler.addQuickElement("title", item['title'])
+        handler.addQuickElement("link", "", {"href": item['link'], "rel": "alternate"})
         if item['pubdate'] is not None:
-            handler.addQuickElement(u"updated", rfc3339_date(item['pubdate']).decode('utf-8'))
-            handler.addQuickElement(u"published", rfc3339_date(item['pubdate']).decode('utf-8'))
+            handler.addQuickElement("updated", rfc3339_date(item['pubdate']))
+            handler.addQuickElement("published", rfc3339_date(item['pubdate']))
 
         # Author information.
         if item['author_name'] is not None:
-            handler.startElement(u"author", {})
-            handler.addQuickElement(u"name", item['author_name'])
+            handler.startElement("author", {})
+            handler.addQuickElement("name", item['author_name'])
             if item['author_email'] is not None:
-                handler.addQuickElement(u"email", item['author_email'])
+                handler.addQuickElement("email", item['author_email'])
             if item['author_link'] is not None:
-                handler.addQuickElement(u"uri", item['author_link'])
-            handler.endElement(u"author")
+                handler.addQuickElement("uri", item['author_link'])
+            handler.endElement("author")
 
         # Unique ID.
         if item['unique_id'] is not None:
             unique_id = item['unique_id']
         else:
             unique_id = get_tag_uri(item['link'], item['pubdate'])
-        handler.addQuickElement(u"id", unique_id)
+        handler.addQuickElement("id", unique_id)
 
         # Summary.
         if item['description'] is not None:
-            handler.addQuickElement(u"summary", item['description'], {u"type": u"html"})
+            handler.addQuickElement("summary", item['description'], {"type": "html"})
 
         # Enclosure.
         if item['enclosure'] is not None:
-            handler.addQuickElement(u"link", '',
-                {u"rel": u"enclosure",
-                 u"href": item['enclosure'].url,
-                 u"length": item['enclosure'].length,
-                 u"type": item['enclosure'].mime_type})
+            handler.addQuickElement("link", '',
+                {"rel": "enclosure",
+                 "href": item['enclosure'].url,
+                 "length": item['enclosure'].length,
+                 "type": item['enclosure'].mime_type})
 
         # Categories.
         for cat in item['categories']:
-            handler.addQuickElement(u"category", u"", {u"term": cat})
+            handler.addQuickElement("category", "", {"term": cat})
 
         # Rights.
         if item['item_copyright'] is not None:
-            handler.addQuickElement(u"rights", item['item_copyright'])
+            handler.addQuickElement("rights", item['item_copyright'])
 
 # This isolates the decision of what the system default is, so calling code can
 # do "feedgenerator.DefaultFeed" instead of "feedgenerator.Rss201rev2Feed".
         a unicode GeoRSS representation.
         """
         if self.is_input_latitude_first:
-            return u' '.join([u'%f %f' % x for x in coords])
+            return ' '.join(['%f %f' % x for x in coords])
         else:
-            return u' '.join([u'%f %f' % (x[1], x[0]) for x in coords])
+            return ' '.join(['%f %f' % (x[1], x[0]) for x in coords])
 
     def add_georss_point(self, handler, coords, w3c_geo=False):
         """
                 lat, lon = coords[:2]
             else:
                 lon, lat = coords[:2]
-            handler.addQuickElement(u'geo:lat', u'%f' % lat)
-            handler.addQuickElement(u'geo:lon', u'%f' % lon)
+            handler.addQuickElement('geo:lat', '%f' % lat)
+            handler.addQuickElement('geo:lon', '%f' % lon)
         else:
-            handler.addQuickElement(u'georss:point', self.georss_coords((coords,)))
+            handler.addQuickElement('georss:point', self.georss_coords((coords,)))
 
     def add_georss_element(self, handler, item, w3c_geo=False):
         """
                 # If a GeoRSS box was given via tuple.
                 if not box_coords is None:
                     if w3c_geo: raise ValueError('Cannot use simple GeoRSS box in W3C Geo feeds.')
-                    handler.addQuickElement(u'georss:box', self.georss_coords(box_coords))
+                    handler.addQuickElement('georss:box', self.georss_coords(box_coords))
             else:
                 # Getting the lower-case geometry type.
                 gtype = str(geom.geom_type).lower()
                     # For formatting consistent w/the GeoRSS simple standard:
                     # http://georss.org/1.0#simple
                     if gtype in ('linestring', 'linearring'):
-                        handler.addQuickElement(u'georss:line', self.georss_coords(geom.coords))
+                        handler.addQuickElement('georss:line', self.georss_coords(geom.coords))
                     elif gtype in ('polygon',):
                         # Only support the exterior ring.
-                        handler.addQuickElement(u'georss:polygon', self.georss_coords(geom[0].coords))
+                        handler.addQuickElement('georss:polygon', self.georss_coords(geom[0].coords))
                     else:
                         raise ValueError('Geometry type "%s" not supported.' % geom.geom_type)
 
 class GeoRSSFeed(Rss201rev2Feed, GeoFeedMixin):
     def rss_attributes(self):
         attrs = super(GeoRSSFeed, self).rss_attributes()
-        attrs[u'xmlns:georss'] = u'http://www.georss.org/georss'
+        attrs['xmlns:georss'] = 'http://www.georss.org/georss'
         return attrs
 
     def add_item_elements(self, handler, item):
 class GeoAtom1Feed(Atom1Feed, GeoFeedMixin):
     def root_attributes(self):
         attrs = super(GeoAtom1Feed, self).root_attributes()
-        attrs[u'xmlns:georss'] = u'http://www.georss.org/georss'
+        attrs['xmlns:georss'] = 'http://www.georss.org/georss'
         return attrs
 
     def add_item_elements(self, handler, item):
 class W3CGeoFeed(Rss201rev2Feed, GeoFeedMixin):
     def rss_attributes(self):
         attrs = super(W3CGeoFeed, self).rss_attributes()
-        attrs[u'xmlns:geo'] = u'http://www.w3.org/2003/01/geo/wgs84_pos#'
+        attrs['xmlns:geo'] = 'http://www.w3.org/2003/01/geo/wgs84_pos#'
         return attrs
 
     def add_item_elements(self, handler, item):

File webhelpers/html/builder.py

 
 """
 import re
-from urllib import quote as url_escape
-from UserDict import DictMixin
+from urllib.parse import quote as url_escape
 
 import markupsafe
 try:
 
 
 def make_tag(tag, *args, **kw):
-    if kw.has_key("c"):
+    if "c" in kw:
         assert not args, "The special 'c' keyword argument cannot be used "\
 "in conjunction with non-keyword arguments"
         args = kw.pop("c")
     >>> format_attrs(p=None)
     literal(u'')
     """
-    strings = [u' %s="%s"' % (_attr_decode(attr), escape(value))
-        for attr, value in sorted(attrs.iteritems())
+    strings = [' %s="%s"' % (_attr_decode(attr), escape(value))
+        for attr, value in sorted(attrs.items())
         if value is not None]
     return literal("".join(strings))
 
 HTML = HTMLBuilder()
 
 # Constants depending on ``literal()`` and/or ``HTML``.
-NL = literal(u"\n")
-EMPTY = literal(u"")
+NL = literal("\n")
+EMPTY = literal("")
 BR = HTML.br(_nl=True)
-_CDATA_START = literal(u"<![CDATA[") 
-_CDATA_END = literal(u"]]>")
+_CDATA_START = literal("<![CDATA[") 
+_CDATA_END = literal("]]>")

File webhelpers/html/render.py

 """An HTML-to-text formatter and HTML sanitizer.
 """
 
-from HTMLParser import HTMLParser
-import htmlentitydefs
+from html.parser import HTMLParser
+import html.entities
 import re
 import textwrap
 
 
     def handle_entityref(self, name):
         name = name.lower()
-        if name not in htmlentitydefs.entitydefs:
+        if name not in html.entities.entitydefs:
             # bad entity, just let it through
             # (like a &var=value in a URL)
             self.handle_data('&'+name)
             return
-        result = htmlentitydefs.entitydefs[name]
+        result = html.entities.entitydefs[name]
         if result.startswith('&'):
             self.handle_charref(result[2:-1])
         else:
 
     def handle_charref(self, name):
         try:
-            self.handle_data(unichr(int(name)))
+            self.handle_data(chr(int(name)))
         except ValueError:
             self.handle_data('&' + name)
         
                 return value.lower()
         return self._default_align
 
-    def __nonzero__(self):
+    def __bool__(self):
         for t in self.text:
             if t:
                 return True
     def add_cell(self, value):
         self.rows[-1].append(value)
 
-    def __nonzero__(self):
+    def __bool__(self):
         return not not self.rows
 
     def to_text(self, context):
 def normalize(text):
     text = re.sub(r'\s+', ' ', text)
     # nbsp:
-    if not isinstance(text, unicode):
+    if not isinstance(text, str):
         text = text.replace('\xa0', ' ')
     return text
 
         prog = os.path.basename(sys.argv[0])
         sys.exit("usage: %s <HTML_FILE" % prog)
     html = sys.stdin.read()
-    print render(html)
+    print(render(html))
 
 if __name__ == "__main__":  main()

File webhelpers/html/tags.py

 import logging
 import os
 import re
-import urllib
-import urlparse
+import urllib.request, urllib.parse, urllib.error
+import urllib.parse
 
 from webhelpers import containers
 from webhelpers.html import escape, HTML, literal, url_escape
         fields.append(field)
     if hidden_fields is not None:
         try:
-            it = hidden_fields.items()
+            it = list(hidden_fields.items())
         except AttributeError:
             it = hidden_fields
         for name, value in it:
     if selected_values is None:
         selected_values = ('',)
     # Turn a single string or integer into a list
-    elif isinstance(selected_values, (basestring, int, long)):
+    elif isinstance(selected_values, (str, int)):
         selected_values = (selected_values,)
     # Cast integer values to strings
-    selected_values = map(unicode, selected_values)
+    selected_values = list(map(str, selected_values))
     # Prepend the prompt
     prompt = attrs.pop("prompt", None)
     if prompt:
                     continue
             else:
                 value = label = opt
-            if not isinstance(value, unicode):
-                value = unicode(value)
-            if not isinstance(label, unicode):  # Preserves literal.
-                label = unicode(label)
+            if not isinstance(value, str):
+                value = str(value)
+            if not isinstance(label, str):  # Preserves literal.
+                label = str(label)
             opt = Option(value, label)
             opts.append(opt)
         return super(Options, class_).__new__(class_, opts)
     
     """
     for a in bool_attrs:
-        if attrs.has_key(a) and attrs[a]:
+        if a in attrs and attrs[a]:
             attrs[a] = a
-        elif attrs.has_key(a):
+        elif a in attrs:
             del attrs[a]
 
 def _set_input_attrs(attrs, type, name, value):

File webhelpers/html/tools.py

 """
 
 import re
-import urllib
+import urllib.request, urllib.parse, urllib.error
 import warnings
 
 from webhelpers.html import HTML, literal, lit_sub, escape
             if not isinstance(option, literal):
                 item = (item[0], escape(option))
             extras.append(item)
-    options_query = urllib.urlencode(extras).replace("+", "%20")
+    options_query = urllib.parse.urlencode(extras).replace("+", "%20")
     protocol = 'mailto:'
 
     email_address_obfuscated = email_address
         flags = re.IGNORECASE
     if highlighter:
         return _legacy_highlight(text, phrase, highlighter, flags)
-    if isinstance(phrase, basestring):
+    if isinstance(phrase, str):
         pat = re.escape(phrase)
         rx = re.compile(pat, flags)
     elif isinstance(phrase, (list, tuple)):
         
     """
     if not text:
-        return literal(u"")
+        return literal("")
     text = escape(text)
     if link == "all":
         return _auto_link_urls(_auto_link_email_addresses(text), **href_attrs)

File webhelpers/markdown.py

 SMART_EMPHASIS = 1        # this_or_that does not become this<i>or</i>that
 HTML_REMOVED_TEXT = "[HTML_REMOVED]" # text used instead of HTML in safe mode
 
-RTL_BIDI_RANGES = ( (u'\u0590', u'\u07FF'),
+RTL_BIDI_RANGES = ( ('\u0590', '\u07FF'),
                     # from Hebrew to Nko (includes Arabic, Syriac and Thaana)
-                    (u'\u2D30', u'\u2D7F'),
+                    ('\u2D30', '\u2D7F'),
                     # Tifinagh
                     )
 
          }
 
 def removeBOM(text, encoding):
-    convert = isinstance(text, unicode)
+    convert = isinstance(text, str)
     for bom in BOMS[encoding]:
         bom = convert and bom.decode(encoding) or bom
         if text.startswith(bom):
 
     ch = text[0]
 
-    if not isinstance(ch, unicode) or not ch.isalpha():
+    if not isinstance(ch, str) or not ch.isalpha():
         return None
 
     else:
         if self.nodeName in ['p', 'li', 'ul', 'ol',
                              'h1', 'h2', 'h3', 'h4', 'h5', 'h6']:
 
-            if not self.attribute_values.has_key("dir"):
+            if "dir" not in self.attribute_values:
                 if self.bidi:
                     bidi = self.bidi
                 else:
             # we'll use "google" as the id
             id = m.group(2).lower()
 
-        if not self.references.has_key(id): # ignore undefined refs
+        if id not in self.references: # ignore undefined refs
             return None
         href, title = self.references[id]
         text = m.group(2)
     def __init__ (self):
 
         self.regExp = {}
-        for key in self.patterns.keys():
+        for key in list(self.patterns.keys()):
             self.regExp[key] = re.compile("^%s$" % self.patterns[key],
                                           re.DOTALL)
 
                         % (ext, extension_module_name) )
             else:
 
-                if configs.has_key(ext):
+                if ext in configs:
                     configs_for_ext = configs[ext]
                 else:
                     configs_for_ext = []
                 
                 x = parts[i]
 
-                if isinstance(x, (str, unicode)):
+                if isinstance(x, str):
                     result = self._applyPattern(x, \
                                 self.inlinePatterns[patternIndex], \
                                 patternIndex)
 
         for i in range(len(parts)):
             x = parts[i]
-            if isinstance(x, (str, unicode)):
+            if isinstance(x, str):
                 parts[i] = self.doc.createTextNode(x)
 
         return parts
 
                             for item in result:
 
-                                if isinstance(item, (str, unicode)):
+                                if isinstance(item, str):
                                     if len(item) > 0:
                                         node.insertChild(position,
                                              self.doc.createTextNode(item))
             self.source = source
 
         if not self.source:
-            return u""
+            return ""
 
         try:
-            self.source = unicode(self.source)
+            self.source = str(self.source)
         except UnicodeDecodeError:
             message(CRITICAL, 'UnicodeDecodeError: Markdown only accepts unicode or ascii  input.')
-            return u""
+            return ""
 
         for pp in self.textPreprocessors:
             self.source = pp.run(self.source)
         self.config = configs
 
     def getConfig(self, key):
-        if self.config.has_key(key):
+        if key in self.config:
             return self.config[key][0]
         else:
             return ""
 
     def getConfigInfo(self):
-        return [(key, self.config[key][1]) for key in self.config.keys()]
+        return [(key, self.config[key][1]) for key in list(self.config.keys())]
 
     def setConfig(self, key, value):
         self.config[key][0] = value
                     'encoding': None }
 
         else:
-            print OPTPARSE_WARNING
+            print(OPTPARSE_WARNING)
             return None
 
     parser = optparse.OptionParser(usage="%prog INPUTFILE [options]")

File webhelpers/media.py

         sys.exit("usage: %s FILES ...\nPrints dimensions of each image")
     for file in files:
         apath = os.path.abspath(file)
-        print "%s:" % apath,
+        print("%s:" % apath, end=' ')
         if not os.path.isfile(file):
-            print "does not exist or is not a plain file"
+            print("does not exist or is not a plain file")
             continue
         width, height = get_dimensions(file)
         if width is None and height is None:
-            print "could not get dimensions"
+            print("could not get dimensions")
         else:
             if width is None:
                 width = "UNKNOWN"
             if height is None:
                 height = "UNKNOWN"
-            print "%s x %s" % (width, height)
+            print("%s x %s" % (width, height))
             
         
 if __name__ == "__main__":  test_get_dimensions()

File webhelpers/mimehelper.py

             if '.' in last_part:
                 has_extension = True
         if 'HTTP_ACCEPT' in self.env:
-            possible_from_accept_header = webob.acceptparse.MIMEAccept('ACCEPT', 
+            possible_from_accept_header = webob.acceptparse.MIMEAccept( 
                 self.env['HTTP_ACCEPT'])
         if has_extension == False:
             if possible_from_accept_header is None:

File webhelpers/misc.py

 
     From recipe in itertools docs.
     """
-    for elm in itertools.ifilterfalse(pred, seq):
+    for elm in itertools.filterfalse(pred, seq):
         return False
     return True
 
 
     From recipe in itertools docs.
     """
-    for elm in itertools.ifilter(pred, seq):
+    for elm in filter(pred, seq):
         return True
     return False
 
 
     From recipe in itertools docs.
     """
-    for elm in itertools.ifilter(pred, seq):
+    for elm in filter(pred, seq):
         return False
     return True
 
     This is mainly used to exclude abstract subclasses.
     """
     if isinstance(it, dict):
-        it = it.itervalues()
-    class_types = (type, types.ClassType)
+        it = iter(list(it.values()))
+    class_types = (type, type)
     ignore = [class_]
     if exclude:
         ignore.extend(exclude)

File webhelpers/number.py

         self.max = None
         self._init_stats()
         
-    def __nonzero__(self):
+    def __bool__(self):
         """The instance is true if it has seen any data."""
         return bool(self.count)
 

File webhelpers/paginate.py

 
 import re
 from string import Template
-import urllib
+import urllib.request, urllib.parse, urllib.error
 import warnings
 
 from webhelpers.html import literal, HTML
 
     def __getitem__(self, range):
         if not isinstance(range, slice):
-            raise Exception, "__getitem__ without slicing not supported"
+            raise Exception("__getitem__ without slicing not supported")
         offset = range.start
         limit = range.stop - range.start
         select = self.obj.offset(offset).limit(limit)
 
     def __getitem__(self, range):
         if not isinstance(range, slice):
-            raise Exception, "__getitem__ without slicing not supported"
+            raise Exception("__getitem__ without slicing not supported")
         return self.obj[range]
 
     def __len__(self):
         # Compute the number of the first and last available page
         if self.item_count > 0:
             self.first_page = 1
-            self.page_count = ((self.item_count - 1) / self.items_per_page) + 1
+            self.page_count = int((self.item_count - 1) / self.items_per_page) + 1
             self.last_page = self.first_page + self.page_count - 1
 
             # Make sure that the requested page number is the range of valid pages
                     first = self.first_item - 1
                     last = self.last_item
                     self.items = list(self.collection[first:last])
-                except TypeError, e:
+                except TypeError as e:
                     if str(e) == "unhashable type":
                         # Assume this means collection is unsliceable.
                         raise TypeError(INCOMPATIBLE_COLLECTION_TYPE)
                 text = HTML.span(c=text, **self.dotdot_attr)
             nav_items.append(text)
 
-        for thispage in xrange(leftmost_page, rightmost_page+1):
+        for thispage in range(leftmost_page, rightmost_page+1):
             # Hilight the current page number and do not use a link
             if thispage == self.page:
                 text = '%s' % (thispage,)
                     # the controller and action manually
                     if config.mapper.explicit:
                         if hasattr(config, 'mapper_dict'):
-                            for k, v in config.mapper_dict.items():
+                            for k, v in list(config.mapper_dict.items()):
                                 if k != self.page_param:
                                     link_params[k] = v