changeset 730:5e9d250ad3ad trunk

Fix for potential duplicate attributes making it through the builder API. Closes #216.
author cmlenz
date Sat, 31 May 2008 21:34:16 +0000
parents be0b4a7b2fd4
children 01bdf155db95
files genshi/builder.py genshi/tests/builder.py
diffstat 2 files changed, 22 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/genshi/builder.py
+++ b/genshi/builder.py
@@ -68,6 +68,11 @@
 Hello, <em>world</em>!
 """
 
+try:
+    set
+except NameError:
+    from sets import Set as set
+
 from genshi.core import Attrs, Namespace, QName, Stream, START, END, TEXT
 
 __all__ = ['Fragment', 'Element', 'ElementFactory', 'tag']
@@ -146,14 +151,13 @@
         return Stream(self._generate())
 
 
-def _value_to_unicode(value):
-    if isinstance(value, unicode):
-        return value
-    return unicode(value)
-
 def _kwargs_to_attrs(kwargs):
-    return [(QName(k.rstrip('_').replace('_', '-')), _value_to_unicode(v))
-            for k, v in kwargs.items() if v is not None]
+    retval = {}
+    for name, value in kwargs.items():
+        name = name.rstrip('_').replace('_', '-')
+        if value is not None and name not in retval:
+            retval[QName(name)] = unicode(value)
+    return Attrs(retval.items())
 
 
 class Element(Fragment):
@@ -240,7 +244,7 @@
     def __init__(self, tag_, **attrib):
         Fragment.__init__(self)
         self.tag = QName(tag_)
-        self.attrib = Attrs(_kwargs_to_attrs(attrib))
+        self.attrib = _kwargs_to_attrs(attrib)
 
     def __call__(self, *args, **kwargs):
         """Append any positional arguments as child nodes, and keyword arguments
@@ -250,7 +254,7 @@
         :rtype: `Element`
         :see: `Fragment.append`
         """
-        self.attrib |= Attrs(_kwargs_to_attrs(kwargs))
+        self.attrib |= _kwargs_to_attrs(kwargs)
         Fragment.__call__(self, *args)
         return self
 
--- a/genshi/tests/builder.py
+++ b/genshi/tests/builder.py
@@ -42,6 +42,15 @@
                           (None, -1, -1)),
                          event)
 
+    def test_duplicate_attributes(self):
+        link = tag.a(href='#1', href_='#2')('Bar')
+        bits = iter(link.generate())
+        self.assertEqual((Stream.START,
+                          ('a', Attrs([('href', "#1")])),
+                          (None, -1, -1)), bits.next())
+        self.assertEqual((Stream.TEXT, u'Bar', (None, -1, -1)), bits.next())
+        self.assertEqual((Stream.END, 'a', (None, -1, -1)), bits.next())
+
     def test_stream_as_child(self):
         xml = list(tag.span(XML('<b>Foo</b>')).generate())
         self.assertEqual(5, len(xml))
Copyright (C) 2012-2017 Edgewall Software