# HG changeset patch # User cmlenz # Date 1212269656 0 # Node ID 5e9d250ad3ad56df76da101bb515f3f50d82418e # Parent be0b4a7b2fd469c4dbf7a8bebaec89182bd639a3 Fix for potential duplicate attributes making it through the builder API. Closes #216. diff --git a/genshi/builder.py b/genshi/builder.py --- a/genshi/builder.py +++ b/genshi/builder.py @@ -68,6 +68,11 @@ Hello, world! """ +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 diff --git a/genshi/tests/builder.py b/genshi/tests/builder.py --- 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('Foo')).generate()) self.assertEqual(5, len(xml))