changeset 854:0d9e87c6cf6e

More work on reducing the size of the diff produced by 2to3.
author cmlenz
date Tue, 10 Nov 2009 22:53:21 +0000
parents 4376010bb97e
children 9598353ed630
files genshi/builder.py genshi/core.py genshi/filters/html.py genshi/filters/i18n.py genshi/filters/tests/html.py genshi/filters/transform.py genshi/input.py genshi/output.py genshi/path.py genshi/template/ast24.py genshi/template/astutil.py genshi/template/eval.py genshi/template/interpolation.py genshi/template/loader.py genshi/template/plugin.py genshi/template/tests/eval.py genshi/template/tests/markup.py genshi/template/tests/text.py genshi/template/text.py genshi/tests/core.py genshi/tests/input.py genshi/tests/util.py genshi/util.py
diffstat 23 files changed, 192 insertions(+), 182 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/builder.py
+++ b/genshi/builder.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -93,7 +93,8 @@
         
         :see: `append`
         """
-        map(self.append, args)
+        for arg in args:
+            self.append(arg)
         return self
 
     def __iter__(self):
@@ -125,7 +126,8 @@
             self.children.extend(node.children)
         elif node is not None:
             try:
-                map(self.append, iter(node))
+                for child in node:
+                    self.append(child)
             except TypeError:
                 self.children.append(node)
 
--- a/genshi/core.py
+++ b/genshi/core.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
--- a/genshi/filters/html.py
+++ b/genshi/filters/html.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -100,7 +100,7 @@
                                         checked = declval in [unicode(v) for v
                                                               in value]
                                     else:
-                                        checked = bool(filter(None, value))
+                                        checked = bool([v for v in value if v])
                                 else:
                                     if declval:
                                         checked = declval == unicode(value)
@@ -414,7 +414,7 @@
         """
         decls = []
         text = self._strip_css_comments(self._replace_unicode_escapes(text))
-        for decl in filter(None, text.split(';')):
+        for decl in [d for d in text.split(';') if d]:
             decl = decl.strip()
             if not decl:
                 continue
--- a/genshi/filters/i18n.py
+++ b/genshi/filters/i18n.py
@@ -147,7 +147,8 @@
         gettext = ctxt.get('_i18n.gettext')
         dgettext = ctxt.get('_i18n.dgettext')
         if ctxt.get('_i18n.domain'):
-            assert callable(dgettext), "No domain gettext function passed"
+            assert hasattr(dgettext, '__call__'), \
+                'No domain gettext function passed'
             gettext = lambda msg: dgettext(ctxt.get('_i18n.domain'), msg)
 
         def _generate():
@@ -318,7 +319,7 @@
         plural_msgbuf = None
 
         ngettext = ctxt.get('_i18n.ungettext')
-        assert callable(ngettext), "No ngettext function available"
+        assert hasattr(ngettext, '__call__'), 'No ngettext function available'
         dngettext = ctxt.get('_i18n.dngettext')
         if not dngettext:
             dngettext = lambda d, s, p, n: ngettext(s, p, n)
@@ -656,9 +657,9 @@
 
                 # If this is an i18n directive, no need to translate text
                 # nodes here
-                is_i18n_directive = filter(None,
-                                           [isinstance(d, ExtractableI18NDirective)
-                                            for d in directives])
+                is_i18n_directive = [b for b in
+                                     [isinstance(d, ExtractableI18NDirective)
+                                      for d in directives] if b]
                 substream = list(self(substream, ctxt,
                                       search_text=not is_i18n_directive))
                 yield kind, (directives, substream), pos
@@ -761,7 +762,7 @@
             elif not skip and search_text and kind is TEXT:
                 if not msgbuf:
                     text = data.strip()
-                    if text and filter(None, [ch.isalpha() for ch in text]):
+                    if text and [ch for ch in text if ch.isalpha()]:
                         yield pos[1], None, text, comment_stack[-1:]
                 else:
                     msgbuf.append(kind, data, pos)
@@ -769,8 +770,9 @@
             elif not skip and msgbuf and kind is END:
                 msgbuf.append(kind, data, pos)
                 if not msgbuf.depth:
-                    yield msgbuf.lineno, None, msgbuf.format(), \
-                                                  filter(None, [msgbuf.comment])
+                    yield msgbuf.lineno, None, msgbuf.format(), [
+                        c for c in msgbuf.comment if c
+                    ]
                     msgbuf = None
 
             elif kind is EXPR or kind is EXEC:
@@ -918,7 +920,7 @@
             self.values[param] = (kind, data, pos)
         else:
             if kind is START: 
-                self.string.append(u'[%d:' % self.order)
+                self.string.append('[%d:' % self.order)
                 self.stack.append(self.order)
                 self.events.setdefault(self.stack[-1],
                                        []).append((kind, data, pos))
@@ -928,14 +930,14 @@
                 self.depth -= 1
                 if self.depth:
                     self.events[self.stack[-1]].append((kind, data, pos))
-                    self.string.append(u']')
+                    self.string.append(']')
                     self.stack.pop()
 
     def format(self):
         """Return a message identifier representing the content in the
         buffer.
         """
-        return u''.join(self.string).strip()
+        return ''.join(self.string).strip()
 
     def translate(self, string, regex=re.compile(r'%\((\w+)\)s')):
         """Interpolate the given message translation with the events in the
--- a/genshi/filters/tests/html.py
+++ b/genshi/filters/tests/html.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -26,7 +26,7 @@
         </p></form>""") | HTMLFormFiller()
         self.assertEquals("""<form><p>
           <input type="text" name="foo"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_input_text_single_value(self):
         html = HTML("""<form><p>
@@ -34,7 +34,7 @@
         </p></form>""") | HTMLFormFiller(data={'foo': 'bar'})
         self.assertEquals("""<form><p>
           <input type="text" name="foo" value="bar"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_input_text_multi_value(self):
         html = HTML("""<form><p>
@@ -42,7 +42,7 @@
         </p></form>""") | HTMLFormFiller(data={'foo': ['bar']})
         self.assertEquals("""<form><p>
           <input type="text" name="foo" value="bar"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_input_hidden_no_value(self):
         html = HTML("""<form><p>
@@ -50,7 +50,7 @@
         </p></form>""") | HTMLFormFiller()
         self.assertEquals("""<form><p>
           <input type="hidden" name="foo"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_input_hidden_single_value(self):
         html = HTML("""<form><p>
@@ -58,7 +58,7 @@
         </p></form>""") | HTMLFormFiller(data={'foo': 'bar'})
         self.assertEquals("""<form><p>
           <input type="hidden" name="foo" value="bar"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_input_hidden_multi_value(self):
         html = HTML("""<form><p>
@@ -66,7 +66,7 @@
         </p></form>""") | HTMLFormFiller(data={'foo': ['bar']})
         self.assertEquals("""<form><p>
           <input type="hidden" name="foo" value="bar"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_textarea_no_value(self):
         html = HTML("""<form><p>
@@ -74,7 +74,7 @@
         </p></form>""") | HTMLFormFiller()
         self.assertEquals("""<form><p>
           <textarea name="foo"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_textarea_single_value(self):
         html = HTML("""<form><p>
@@ -82,7 +82,7 @@
         </p></form>""") | HTMLFormFiller(data={'foo': 'bar'})
         self.assertEquals("""<form><p>
           <textarea name="foo">bar</textarea>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_textarea_multi_value(self):
         html = HTML("""<form><p>
@@ -90,7 +90,7 @@
         </p></form>""") | HTMLFormFiller(data={'foo': ['bar']})
         self.assertEquals("""<form><p>
           <textarea name="foo">bar</textarea>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_input_checkbox_no_value(self):
         html = HTML("""<form><p>
@@ -98,7 +98,7 @@
         </p></form>""") | HTMLFormFiller()
         self.assertEquals("""<form><p>
           <input type="checkbox" name="foo"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_input_checkbox_single_value_auto(self):
         html = HTML("""<form><p>
@@ -106,10 +106,10 @@
         </p></form>""")
         self.assertEquals("""<form><p>
           <input type="checkbox" name="foo"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ''})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': ''})).render())
         self.assertEquals("""<form><p>
           <input type="checkbox" name="foo" checked="checked"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': 'on'})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': 'on'})).render())
 
     def test_fill_input_checkbox_single_value_defined(self):
         html = HTML("""<form><p>
@@ -117,10 +117,10 @@
         </p></form>""")
         self.assertEquals("""<form><p>
           <input type="checkbox" name="foo" value="1" checked="checked"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '1'})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': '1'})).render())
         self.assertEquals("""<form><p>
           <input type="checkbox" name="foo" value="1"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '2'})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': '2'})).render())
 
     def test_fill_input_checkbox_multi_value_auto(self):
         html = HTML("""<form><p>
@@ -128,10 +128,10 @@
         </p></form>""")
         self.assertEquals("""<form><p>
           <input type="checkbox" name="foo"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': []})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': []})).render())
         self.assertEquals("""<form><p>
           <input type="checkbox" name="foo" checked="checked"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['on']})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': ['on']})).render())
 
     def test_fill_input_checkbox_multi_value_defined(self):
         html = HTML("""<form><p>
@@ -139,10 +139,10 @@
         </p></form>""")
         self.assertEquals("""<form><p>
           <input type="checkbox" name="foo" value="1" checked="checked"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['1']})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': ['1']})).render())
         self.assertEquals("""<form><p>
           <input type="checkbox" name="foo" value="1"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['2']})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': ['2']})).render())
 
     def test_fill_input_radio_no_value(self):
         html = HTML("""<form><p>
@@ -150,7 +150,7 @@
         </p></form>""") | HTMLFormFiller()
         self.assertEquals("""<form><p>
           <input type="radio" name="foo"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_input_radio_single_value(self):
         html = HTML("""<form><p>
@@ -158,10 +158,10 @@
         </p></form>""")
         self.assertEquals("""<form><p>
           <input type="radio" name="foo" value="1" checked="checked"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '1'})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': '1'})).render())
         self.assertEquals("""<form><p>
           <input type="radio" name="foo" value="1"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': '2'})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': '2'})).render())
 
     def test_fill_input_radio_multi_value(self):
         html = HTML("""<form><p>
@@ -169,10 +169,10 @@
         </p></form>""")
         self.assertEquals("""<form><p>
           <input type="radio" name="foo" value="1" checked="checked"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['1']})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': ['1']})).render())
         self.assertEquals("""<form><p>
           <input type="radio" name="foo" value="1"/>
-        </p></form>""", unicode(html | HTMLFormFiller(data={'foo': ['2']})))
+        </p></form>""", (html | HTMLFormFiller(data={'foo': ['2']})).render())
 
     def test_fill_select_no_value_auto(self):
         html = HTML("""<form><p>
@@ -188,7 +188,7 @@
             <option>2</option>
             <option>3</option>
           </select>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_select_no_value_defined(self):
         html = HTML("""<form><p>
@@ -204,7 +204,7 @@
             <option value="2">2</option>
             <option value="3">3</option>
           </select>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_select_single_value_auto(self):
         html = HTML("""<form><p>
@@ -220,7 +220,7 @@
             <option>2</option>
             <option>3</option>
           </select>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_select_single_value_defined(self):
         html = HTML("""<form><p>
@@ -236,7 +236,7 @@
             <option value="2">2</option>
             <option value="3">3</option>
           </select>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_select_multi_value_auto(self):
         html = HTML("""<form><p>
@@ -252,7 +252,7 @@
             <option>2</option>
             <option selected="selected">3</option>
           </select>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_select_multi_value_defined(self):
         html = HTML("""<form><p>
@@ -268,7 +268,7 @@
             <option value="2">2</option>
             <option value="3" selected="selected">3</option>
           </select>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_option_segmented_text(self):
         html = MarkupTemplate("""<form>
@@ -280,7 +280,7 @@
           <select name="foo">
             <option value="1" selected="selected">foo 1</option>
           </select>
-        </form>""", unicode(html))
+        </form>""", html.render())
 
     def test_fill_option_segmented_text_no_value(self):
         html = MarkupTemplate("""<form>
@@ -292,10 +292,10 @@
           <select name="foo">
             <option selected="selected">foo 1 bar</option>
           </select>
-        </form>""", unicode(html))
+        </form>""", html.render())
 
     def test_fill_option_unicode_value(self):
-        html = HTML(u"""<form>
+        html = HTML("""<form>
           <select name="foo">
             <option value="&ouml;">foo</option>
           </select>
@@ -304,7 +304,7 @@
           <select name="foo">
             <option value="ö" selected="selected">foo</option>
           </select>
-        </form>""", unicode(html))
+        </form>""", html.render(encoding=None))
 
     def test_fill_input_password_disabled(self):
         html = HTML("""<form><p>
@@ -312,7 +312,7 @@
         </p></form>""") | HTMLFormFiller(data={'pass': 'bar'})
         self.assertEquals("""<form><p>
           <input type="password" name="pass"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
     def test_fill_input_password_enabled(self):
         html = HTML("""<form><p>
@@ -320,146 +320,147 @@
         </p></form>""") | HTMLFormFiller(data={'pass': '1234'}, passwords=True)
         self.assertEquals("""<form><p>
           <input type="password" name="pass" value="1234"/>
-        </p></form>""", unicode(html))
+        </p></form>""", html.render())
 
 
 class HTMLSanitizerTestCase(unittest.TestCase):
 
     def test_sanitize_unchanged(self):
         html = HTML('<a href="#">fo<br />o</a>')
-        self.assertEquals(u'<a href="#">fo<br/>o</a>',
-                          unicode(html | HTMLSanitizer()))
+        self.assertEquals('<a href="#">fo<br/>o</a>',
+                          (html | HTMLSanitizer()).render())
         html = HTML('<a href="#with:colon">foo</a>')
-        self.assertEquals(u'<a href="#with:colon">foo</a>',
-                          unicode(html | HTMLSanitizer()))
+        self.assertEquals('<a href="#with:colon">foo</a>',
+                          (html | HTMLSanitizer()).render())
 
     def test_sanitize_escape_text(self):
         html = HTML('<a href="#">fo&amp;</a>')
-        self.assertEquals(u'<a href="#">fo&amp;</a>',
-                          unicode(html | HTMLSanitizer()))
+        self.assertEquals('<a href="#">fo&amp;</a>',
+                          (html | HTMLSanitizer()).render())
         html = HTML('<a href="#">&lt;foo&gt;</a>')
-        self.assertEquals(u'<a href="#">&lt;foo&gt;</a>',
-                          unicode(html | HTMLSanitizer()))
+        self.assertEquals('<a href="#">&lt;foo&gt;</a>',
+                          (html | HTMLSanitizer()).render())
 
     def test_sanitize_entityref_text(self):
         html = HTML('<a href="#">fo&ouml;</a>')
         self.assertEquals(u'<a href="#">foö</a>',
-                          unicode(html | HTMLSanitizer()))
+                          (html | HTMLSanitizer()).render(encoding=None))
 
     def test_sanitize_escape_attr(self):
         html = HTML('<div title="&lt;foo&gt;"></div>')
-        self.assertEquals(u'<div title="&lt;foo&gt;"/>',
-                          unicode(html | HTMLSanitizer()))
+        self.assertEquals('<div title="&lt;foo&gt;"/>',
+                          (html | HTMLSanitizer()).render())
 
     def test_sanitize_close_empty_tag(self):
         html = HTML('<a href="#">fo<br>o</a>')
-        self.assertEquals(u'<a href="#">fo<br/>o</a>',
-                          unicode(html | HTMLSanitizer()))
+        self.assertEquals('<a href="#">fo<br/>o</a>',
+                          (html | HTMLSanitizer()).render())
 
     def test_sanitize_invalid_entity(self):
         html = HTML('&junk;')
-        self.assertEquals('&amp;junk;', unicode(html | HTMLSanitizer()))
+        self.assertEquals('&amp;junk;', (html | HTMLSanitizer()).render())
 
     def test_sanitize_remove_script_elem(self):
         html = HTML('<script>alert("Foo")</script>')
-        self.assertEquals(u'', unicode(html | HTMLSanitizer()))
+        self.assertEquals('', (html | HTMLSanitizer()).render())
         html = HTML('<SCRIPT SRC="http://example.com/"></SCRIPT>')
-        self.assertEquals(u'', unicode(html | HTMLSanitizer()))
+        self.assertEquals('', (html | HTMLSanitizer()).render())
         self.assertRaises(ParseError, HTML, '<SCR\0IPT>alert("foo")</SCR\0IPT>')
         self.assertRaises(ParseError, HTML,
                           '<SCRIPT&XYZ SRC="http://example.com/"></SCRIPT>')
 
     def test_sanitize_remove_onclick_attr(self):
         html = HTML('<div onclick=\'alert("foo")\' />')
-        self.assertEquals(u'<div/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<div/>', (html | HTMLSanitizer()).render())
 
     def test_sanitize_remove_input_password(self):
         html = HTML('<form><input type="password" /></form>')
-        self.assertEquals(u'<form/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<form/>', (html | HTMLSanitizer()).render())
 
     def test_sanitize_remove_comments(self):
         html = HTML('''<div><!-- conditional comment crap --></div>''')
-        self.assertEquals(u'<div/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<div/>', (html | HTMLSanitizer()).render())
 
     def test_sanitize_remove_style_scripts(self):
         sanitizer = HTMLSanitizer(safe_attrs=HTMLSanitizer.SAFE_ATTRS | set(['style']))
         # Inline style with url() using javascript: scheme
         html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"))\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         # Inline style with url() using javascript: scheme, using control char
         html = HTML('<DIV STYLE=\'background: url(&#1;javascript:alert("foo"))\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         # Inline style with url() using javascript: scheme, in quotes
         html = HTML('<DIV STYLE=\'background: url("javascript:alert(foo)")\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         # IE expressions in CSS not allowed
         html = HTML('<DIV STYLE=\'width: expression(alert("foo"));\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         html = HTML('<DIV STYLE=\'width: e/**/xpression(alert("foo"));\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         html = HTML('<DIV STYLE=\'background: url(javascript:alert("foo"));'
                                  'color: #fff\'>')
-        self.assertEquals(u'<div style="color: #fff"/>',
-                          unicode(html | sanitizer))
+        self.assertEquals('<div style="color: #fff"/>',
+                          (html | sanitizer).render())
         # Inline style with url() using javascript: scheme, using unicode
         # escapes
         html = HTML('<DIV STYLE=\'background: \\75rl(javascript:alert("foo"))\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         html = HTML('<DIV STYLE=\'background: \\000075rl(javascript:alert("foo"))\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         html = HTML('<DIV STYLE=\'background: \\75 rl(javascript:alert("foo"))\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         html = HTML('<DIV STYLE=\'background: \\000075 rl(javascript:alert("foo"))\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         html = HTML('<DIV STYLE=\'background: \\000075\r\nrl(javascript:alert("foo"))\'>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
 
     def test_sanitize_remove_style_phishing(self):
         sanitizer = HTMLSanitizer(safe_attrs=HTMLSanitizer.SAFE_ATTRS | set(['style']))
         # The position property is not allowed
         html = HTML('<div style="position:absolute;top:0"></div>')
-        self.assertEquals(u'<div style="top:0"/>', unicode(html | sanitizer))
+        self.assertEquals('<div style="top:0"/>', (html | sanitizer).render())
         # Normal margins get passed through
         html = HTML('<div style="margin:10px 20px"></div>')
-        self.assertEquals(u'<div style="margin:10px 20px"/>', unicode(html | sanitizer))
+        self.assertEquals('<div style="margin:10px 20px"/>',
+                          (html | sanitizer).render())
         # But not negative margins
         html = HTML('<div style="margin:-1000px 0 0"></div>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         html = HTML('<div style="margin-left:-2000px 0 0"></div>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
         html = HTML('<div style="margin-left:1em 1em 1em -4000px"></div>')
-        self.assertEquals(u'<div/>', unicode(html | sanitizer))
+        self.assertEquals('<div/>', (html | sanitizer).render())
 
     def test_sanitize_remove_src_javascript(self):
         html = HTML('<img src=\'javascript:alert("foo")\'>')
-        self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
         # Case-insensitive protocol matching
         html = HTML('<IMG SRC=\'JaVaScRiPt:alert("foo")\'>')
-        self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
         # Grave accents (not parsed)
         self.assertRaises(ParseError, HTML,
                           '<IMG SRC=`javascript:alert("RSnake says, \'foo\'")`>')
         # Protocol encoded using UTF-8 numeric entities
         html = HTML('<IMG SRC=\'&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;'
                     '&#112;&#116;&#58;alert("foo")\'>')
-        self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
         # Protocol encoded using UTF-8 numeric entities without a semicolon
         # (which is allowed because the max number of digits is used)
         html = HTML('<IMG SRC=\'&#0000106&#0000097&#0000118&#0000097'
                     '&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116'
                     '&#0000058alert("foo")\'>')
-        self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
         # Protocol encoded using UTF-8 numeric hex entities without a semicolon
         # (which is allowed because the max number of digits is used)
         html = HTML('<IMG SRC=\'&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69'
                     '&#x70&#x74&#x3A;alert("foo")\'>')
-        self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
         # Embedded tab character in protocol
         html = HTML('<IMG SRC=\'jav\tascript:alert("foo");\'>')
-        self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
         # Embedded tab character in protocol, but encoded this time
         html = HTML('<IMG SRC=\'jav&#x09;ascript:alert("foo");\'>')
-        self.assertEquals(u'<img/>', unicode(html | HTMLSanitizer()))
+        self.assertEquals('<img/>', (html | HTMLSanitizer()).render())
 
 
 def suite():
--- a/genshi/filters/transform.py
+++ b/genshi/filters/transform.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2007 Edgewall Software
+# Copyright (C) 2007-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -876,7 +876,7 @@
         :param stream: the marked event stream to filter
         """
         for event in stream:
-            print>>self.fileobj, self.prefix + str(event)
+            self.fileobj.write('%s%s\n' % (self.prefix, event))
             yield event
 
 
--- a/genshi/input.py
+++ b/genshi/input.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2007 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
--- a/genshi/output.py
+++ b/genshi/output.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -265,7 +265,7 @@
                 if sysid:
                     buf.append(' "%s"')
                 buf.append('>\n')
-                yield Markup(''.join(buf)) % filter(None, data)
+                yield Markup(''.join(buf)) % tuple([p for p in data if p])
                 have_doctype = True
 
             elif kind is START_CDATA:
@@ -381,7 +381,7 @@
                 if sysid:
                     buf.append(' "%s"')
                 buf.append('>\n')
-                yield Markup(''.join(buf)) % filter(None, data)
+                yield Markup(''.join(buf)) % tuple([p for p in data if p])
                 have_doctype = True
 
             elif kind is XML_DECL and not have_decl and not drop_xml_decl:
@@ -518,7 +518,7 @@
                 if sysid:
                     buf.append(' "%s"')
                 buf.append('>\n')
-                yield Markup(''.join(buf)) % filter(None, data)
+                yield Markup(''.join(buf)) % tuple([p for p in data if p])
                 have_doctype = True
 
             elif kind is PI:
--- a/genshi/path.py
+++ b/genshi/path.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -278,7 +278,7 @@
                 return []
             pi = [0]
             s = 0
-            for i in xrange(1, len(f)):
+            for i in range(1, len(f)):
                 while s > 0 and not nodes_equal(f[s], f[i]):
                     s = pi[s-1]
                 if nodes_equal(f[s], f[i]):
@@ -537,7 +537,7 @@
                     self.strategies.append(strategy_class(path))
                     break
             else:
-                raise NotImplemented, "This path is not implemented"
+                raise NotImplemented('No strategy found for path')
 
     def __repr__(self):
         paths = []
@@ -667,9 +667,9 @@
     def __init__(self, text, filename=None, lineno=-1):
         self.filename = filename
         self.lineno = lineno
-        self.tokens = filter(None, [dqstr or sqstr or number or token or name
-                                    for dqstr, sqstr, number, token, name in
-                                    self._tokenize(text)])
+        self.tokens = [t for t in [dqstr or sqstr or number or token or name
+                                   for dqstr, sqstr, number, token, name in
+                                   self._tokenize(text)] if t]
         self.pos = 0
 
     # Tokenizer
--- a/genshi/template/ast24.py
+++ b/genshi/template/ast24.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2008 Edgewall Software
+# Copyright (C) 2008-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
--- a/genshi/template/astutil.py
+++ b/genshi/template/astutil.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2008 Edgewall Software
+# Copyright (C) 2008-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
--- a/genshi/template/eval.py
+++ b/genshi/template/eval.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
--- a/genshi/template/interpolation.py
+++ b/genshi/template/interpolation.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2007-2008 Edgewall Software
+# Copyright (C) 2007-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
--- a/genshi/template/loader.py
+++ b/genshi/template/loader.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -326,7 +326,7 @@
                         filename[len(prefix):].lstrip('/\\')
                     )
                     return filepath, filename, fileobj, uptodate
-            raise TemplateNotFound(filename, delegates.keys())
+            raise TemplateNotFound(filename, list(delegates.keys()))
         return _dispatch_by_prefix
 
 
--- a/genshi/template/plugin.py
+++ b/genshi/template/plugin.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # Copyright (C) 2006 Matthew Good
 # All rights reserved.
 #
@@ -48,7 +48,8 @@
         auto_reload = options.get('genshi.auto_reload', '1')
         if isinstance(auto_reload, basestring):
             auto_reload = auto_reload.lower() in ('1', 'on', 'yes', 'true')
-        search_path = filter(None, options.get('genshi.search_path', '').split(':'))
+        search_path = [p for p in
+                       options.get('genshi.search_path', '').split(':') if p]
         self.use_package_naming = not search_path
         try:
             max_cache_size = int(options.get('genshi.max_cache_size', 25))
--- a/genshi/template/tests/eval.py
+++ b/genshi/template/tests/eval.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -637,7 +637,7 @@
     def test_import_in_def(self):
         suite = Suite("""def fun():
     from itertools import ifilter
-    return ifilter(None, xrange(3))
+    return ifilter(None, range(3))
 """)
         data = Context()
         suite.execute(data)
--- a/genshi/template/tests/markup.py
+++ b/genshi/template/tests/markup.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -211,23 +211,23 @@
         Verify that a code block processing instruction with trailing space
         does not cause a syntax error (see ticket #127).
         """
-        MarkupTemplate(u"""<foo>
+        MarkupTemplate("""<foo>
           <?python
             bar = 42
           ?>
         </foo>""")
 
     def test_exec_import(self):
-        tmpl = MarkupTemplate(u"""<?python from datetime import timedelta ?>
+        tmpl = MarkupTemplate("""<?python from datetime import timedelta ?>
         <div xmlns:py="http://genshi.edgewall.org/">
           ${timedelta(days=2)}
         </div>""")
-        self.assertEqual(u"""<div>
+        self.assertEqual("""<div>
           2 days, 0:00:00
         </div>""", str(tmpl.generate()))
 
     def test_exec_def(self):
-        tmpl = MarkupTemplate(u"""
+        tmpl = MarkupTemplate("""
         <?python
         def foo():
             return 42
@@ -235,7 +235,7 @@
         <div xmlns:py="http://genshi.edgewall.org/">
           ${foo()}
         </div>""")
-        self.assertEqual(u"""<div>
+        self.assertEqual("""<div>
           42
         </div>""", str(tmpl.generate()))
 
--- a/genshi/template/tests/text.py
+++ b/genshi/template/tests/text.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2008 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -53,12 +53,14 @@
     def test_latin1_encoded(self):
         text = u'$foo\xf6$bar'.encode('iso-8859-1')
         tmpl = OldTextTemplate(text, encoding='iso-8859-1')
-        self.assertEqual(u'x\xf6y', unicode(tmpl.generate(foo='x', bar='y')))
+        self.assertEqual(u'x\xf6y',
+                         tmpl.generate(foo='x', bar='y').render(encoding=None))
 
     def test_unicode_input(self):
         text = u'$foo\xf6$bar'
         tmpl = OldTextTemplate(text)
-        self.assertEqual(u'x\xf6y', unicode(tmpl.generate(foo='x', bar='y')))
+        self.assertEqual(u'x\xf6y',
+                         tmpl.generate(foo='x', bar='y').render(encoding=None))
 
     def test_empty_lines1(self):
         tmpl = OldTextTemplate("""Your items:
@@ -144,12 +146,14 @@
     def test_latin1_encoded(self):
         text = u'$foo\xf6$bar'.encode('iso-8859-1')
         tmpl = NewTextTemplate(text, encoding='iso-8859-1')
-        self.assertEqual(u'x\xf6y', unicode(tmpl.generate(foo='x', bar='y')))
+        self.assertEqual(u'x\xf6y',
+                         tmpl.generate(foo='x', bar='y').render(encoding=None))
 
     def test_unicode_input(self):
         text = u'$foo\xf6$bar'
         tmpl = NewTextTemplate(text)
-        self.assertEqual(u'x\xf6y', unicode(tmpl.generate(foo='x', bar='y')))
+        self.assertEqual(u'x\xf6y',
+                         tmpl.generate(foo='x', bar='y').render(encoding=None))
 
     def test_empty_lines1(self):
         tmpl = NewTextTemplate("""Your items:
--- a/genshi/template/text.py
+++ b/genshi/template/text.py
@@ -144,10 +144,10 @@
             raise ValueError('delimiers tuple must have exactly four elements')
         self._delims = delims
         self._directive_re = re.compile(self._DIRECTIVE_RE % tuple(
-            map(re.escape, delims)
+            [re.escape(d) for d in delims]
         ), re.DOTALL)
         self._escape_re = re.compile(self._ESCAPE_RE % tuple(
-            map(re.escape, delims[::2])
+            [re.escape(d) for d in delims[::2]]
         ))
     delimiters = property(_get_delims, _set_delims, """\
     The delimiters for directives and comments. This should be a four item tuple
--- a/genshi/tests/core.py
+++ b/genshi/tests/core.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
--- a/genshi/tests/input.py
+++ b/genshi/tests/input.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -27,7 +27,7 @@
         events = list(XMLParser(StringIO(text)))
         kind, data, pos = events[1]
         self.assertEqual(Stream.TEXT, kind)
-        self.assertEqual(u'foo bar', data)
+        self.assertEqual('foo bar', data)
         self.assertEqual((None, 1, 6), pos)
 
     def test_text_node_pos_multi_line(self):
@@ -36,7 +36,7 @@
         events = list(XMLParser(StringIO(text)))
         kind, data, pos = events[1]
         self.assertEqual(Stream.TEXT, kind)
-        self.assertEqual(u'foo\nbar', data)
+        self.assertEqual('foo\nbar', data)
         self.assertEqual((None, 1, -1), pos)
 
     def test_element_attribute_order(self):
@@ -45,10 +45,10 @@
         kind, data, pos = events[0]
         self.assertEqual(Stream.START, kind)
         tag, attrib = data
-        self.assertEqual(u'elem', tag)
-        self.assertEqual((u'title', u'baz'), attrib[0])
-        self.assertEqual((u'id', u'foo'), attrib[1])
-        self.assertEqual((u'class', u'bar'), attrib[2])
+        self.assertEqual('elem', tag)
+        self.assertEqual(('title', 'baz'), attrib[0])
+        self.assertEqual(('id', 'foo'), attrib[1])
+        self.assertEqual(('class', 'bar'), attrib[2])
 
     def test_unicode_input(self):
         text = u'<div>\u2013</div>'
@@ -120,7 +120,7 @@
         events = list(HTMLParser(StringIO(text)))
         kind, data, pos = events[1]
         self.assertEqual(Stream.TEXT, kind)
-        self.assertEqual(u'foo bar', data)
+        self.assertEqual('foo bar', data)
         self.assertEqual((None, 1, 6), pos)
 
     def test_text_node_pos_multi_line(self):
@@ -129,7 +129,7 @@
         events = list(HTMLParser(StringIO(text)))
         kind, data, pos = events[1]
         self.assertEqual(Stream.TEXT, kind)
-        self.assertEqual(u'foo\nbar', data)
+        self.assertEqual('foo\nbar', data)
         self.assertEqual((None, 1, 6), pos)
 
     def test_input_encoding_text(self):
@@ -174,15 +174,15 @@
         events = list(HTMLParser(StringIO(text)))
         kind, (target, data), pos = events[0]
         self.assertEqual(Stream.PI, kind)
-        self.assertEqual(u'php', target)
-        self.assertEqual(u'echo "Foobar"', data)
+        self.assertEqual('php', target)
+        self.assertEqual('echo "Foobar"', data)
 
     def test_xmldecl(self):
         text = '<?xml version="1.0" ?><root />'
         events = list(XMLParser(StringIO(text)))
         kind, (version, encoding, standalone), pos = events[0]
         self.assertEqual(Stream.XML_DECL, kind)
-        self.assertEqual(u'1.0', version)
+        self.assertEqual('1.0', version)
         self.assertEqual(None, encoding)
         self.assertEqual(-1, standalone)
 
@@ -191,8 +191,8 @@
         events = list(XMLParser(StringIO(text)))
         kind, (version, encoding, standalone), pos = events[0]
         self.assertEqual(Stream.XML_DECL, kind)
-        self.assertEqual(u'1.0', version)
-        self.assertEqual(u'utf-8', encoding)
+        self.assertEqual('1.0', version)
+        self.assertEqual('utf-8', encoding)
         self.assertEqual(-1, standalone)
 
     def test_xmldecl_standalone(self):
@@ -200,7 +200,7 @@
         events = list(XMLParser(StringIO(text)))
         kind, (version, encoding, standalone), pos = events[0]
         self.assertEqual(Stream.XML_DECL, kind)
-        self.assertEqual(u'1.0', version)
+        self.assertEqual('1.0', version)
         self.assertEqual(None, encoding)
         self.assertEqual(1, standalone)
 
@@ -209,8 +209,8 @@
         events = list(HTMLParser(StringIO(text)))
         kind, (target, data), pos = events[0]
         self.assertEqual(Stream.PI, kind)
-        self.assertEqual(u'php', target)
-        self.assertEqual(u'echo "Foobar" ?', data)
+        self.assertEqual('php', target)
+        self.assertEqual('echo "Foobar" ?', data)
 
     def test_out_of_order_tags1(self):
         text = '<span><b>Foobar</span></b>'
--- a/genshi/tests/util.py
+++ b/genshi/tests/util.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006 Edgewall Software
+# Copyright (C) 2006,2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -29,8 +29,8 @@
         item_a = cache._dict['A']
         self.assertEqual('A', item_a.key)
         self.assertEqual(0, item_a.value)
-        self.assertEqual(None, item_a.previous)
-        self.assertEqual(None, item_a.next)
+        self.assertEqual(None, item_a.prv)
+        self.assertEqual(None, item_a.nxt)
 
         cache['B'] = 1
         self.assertEqual(2, len(cache))
@@ -40,12 +40,12 @@
         item_b = cache._dict['B']
         self.assertEqual('A', item_a.key)
         self.assertEqual(0, item_a.value)
-        self.assertEqual(item_b, item_a.previous)
-        self.assertEqual(None, item_a.next)
+        self.assertEqual(item_b, item_a.prv)
+        self.assertEqual(None, item_a.nxt)
         self.assertEqual('B', item_b.key)
         self.assertEqual(1, item_b.value)
-        self.assertEqual(None, item_b.previous)
-        self.assertEqual(item_a, item_b.next)
+        self.assertEqual(None, item_b.prv)
+        self.assertEqual(item_a, item_b.nxt)
 
         cache['C'] = 2
         self.assertEqual(2, len(cache))
@@ -55,12 +55,12 @@
         item_c = cache._dict['C']
         self.assertEqual('B', item_b.key)
         self.assertEqual(1, item_b.value)
-        self.assertEqual(item_c, item_b.previous)
-        self.assertEqual(None, item_b.next)
+        self.assertEqual(item_c, item_b.prv)
+        self.assertEqual(None, item_b.nxt)
         self.assertEqual('C', item_c.key)
         self.assertEqual(2, item_c.value)
-        self.assertEqual(None, item_c.previous)
-        self.assertEqual(item_b, item_c.next)
+        self.assertEqual(None, item_c.prv)
+        self.assertEqual(item_b, item_c.nxt)
 
     def test_getitem(self):
         cache = LRUCache(2)
@@ -76,12 +76,12 @@
         item_b = cache._dict['B']
         self.assertEqual('A', item_a.key)
         self.assertEqual(0, item_a.value)
-        self.assertEqual(None, item_a.previous)
-        self.assertEqual(item_b, item_a.next)
+        self.assertEqual(None, item_a.prv)
+        self.assertEqual(item_b, item_a.nxt)
         self.assertEqual('B', item_b.key)
         self.assertEqual(1, item_b.value)
-        self.assertEqual(item_a, item_b.previous)
-        self.assertEqual(None, item_b.next)
+        self.assertEqual(item_a, item_b.prv)
+        self.assertEqual(None, item_b.nxt)
 
 
 def suite():
--- a/genshi/util.py
+++ b/genshi/util.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# Copyright (C) 2006-2007 Edgewall Software
+# Copyright (C) 2006-2009 Edgewall Software
 # All rights reserved.
 #
 # This software is licensed as described in the file COPYING, which
@@ -59,7 +59,7 @@
 
     class _Item(object):
         def __init__(self, key, value):
-            self.previous = self.next = None
+            self.prv = self.nxt = None
             self.key = key
             self.value = value
         def __repr__(self):
@@ -78,7 +78,7 @@
         cur = self.head
         while cur:
             yield cur.key
-            cur = cur.next
+            cur = cur.nxt
 
     def __len__(self):
         return len(self._dict)
@@ -103,10 +103,10 @@
         return repr(self._dict)
 
     def _insert_item(self, item):
-        item.previous = None
-        item.next = self.head
+        item.prv = None
+        item.nxt = self.head
         if self.head is not None:
-            self.head.previous = item
+            self.head.prv = item
         else:
             self.tail = item
         self.head = item
@@ -117,8 +117,8 @@
             olditem = self._dict[self.tail.key]
             del self._dict[self.tail.key]
             if self.tail != self.head:
-                self.tail = self.tail.previous
-                self.tail.next = None
+                self.tail = self.tail.prv
+                self.tail.nxt = None
             else:
                 self.head = self.tail = None
 
@@ -126,16 +126,16 @@
         if self.head == item:
             return
 
-        previous = item.previous
-        previous.next = item.next
-        if item.next is not None:
-            item.next.previous = previous
+        prv = item.prv
+        prv.nxt = item.nxt
+        if item.nxt is not None:
+            item.nxt.prv = prv
         else:
-            self.tail = previous
+            self.tail = prv
 
-        item.previous = None
-        item.next = self.head
-        self.head.previous = self.head = item
+        item.prv = None
+        item.nxt = self.head
+        self.head.prv = self.head = item
 
 
 def flatten(items):
Copyright (C) 2012-2017 Edgewall Software