Commits

jason kirtland committed 6c5d262

Tiptoe around possible operator overloading in user-supplied Markup class when generating tags.

Comments (0)

Files changed (4)

flatland/out/generic.py

     return _id_invalid_re.sub(u'', string)
 
 
+def _unpack(html_string):
+    """Extract HTML unicode from a __html__() interface."""
+    unpacked = html_string.__html__()
+    if unpacked.__class__ is unicode:
+        return unpacked
+    return unicode(unpacked)
+
+
 def _markup_escape(string):
     if not string:
         return u''
     elif hasattr(string, '__html__'):
-        return string.__html__()
+        return _unpack(string)
     else:
         return string. \
                replace(u'&', u'&'). \

flatland/out/genshi_06.py

 from genshi.template.interpolation import interpolate
 
 
-from flatland.out.generic import transform, Context
+from flatland.out.generic import _unpack, transform, Context
 
 
 __all__ = ('setup',)
         elif kind is EXPR:
             value = _eval_expr(data, ctxt, vars)
             if hasattr(value, '__html__'):
-                value = value.__html__()
+                value = _unpack(value)
             if hasattr(value, '__next__') or hasattr(value, 'next'):
                 while hasattr(value, '__next__') or hasattr(value, 'next'):
                     value = list(value)

flatland/out/markup.py

 from collections import defaultdict
 
-from flatland.out.generic import Context, transform
+from flatland.out.generic import Context, transform, _unpack
 from flatland.out.util import parse_trool
 
 
         if not new_contents:
             new_contents = u''
         elif hasattr(new_contents, '__html__'):
-            new_contents = new_contents.__html__()
+            new_contents = _unpack(new_contents)
         self.contents = self._markup(new_contents)
 
         if self._context['ordered_attributes']:
 
     def __call__(self, bind=None, **attributes):
         header = self._open(bind, attributes)
-        if not self.contents:
+        contents = self.contents
+        if not contents:
             if not self._always_paired:
                 if self._context.xml:
                     return self._markup(header + u' />')
                 elif self._html_dangle:
                     return self._markup(header + u'>')
-        return self._markup(header + u'>' + self.contents + self._close())
+        if hasattr(contents, '__html__'):
+            contents = _unpack(contents)
+        return self._markup(header + u'>' + contents + self._close())
 
     def __html__(self):
         return self()
     if not string:
         return u''
     elif hasattr(string, '__html__'):
-        return string.__html__()
+        return _unpack(string)
     else:
         return string. \
                replace(u'&', u'&'). \

tests/markup/test_generator.py

     """xyzzy"""
     gen.textarea.open(el, contents=u'xyzzy')
     return gen.textarea.contents
+
+
+def test_Markup_concatenation():
+    from flatland.out.generic import Markup as Markup
+    implementations = [Markup]
+    try:
+        from jinja2 import Markup
+        implementations.append(Markup)
+    except ImportError:
+        pass
+    try:
+        from markupsafe import Markup
+        implementations.append(Markup)
+    except ImportError:
+        pass
+
+    for impl in implementations:
+        yield _generate_markup_test(impl), impl.__module__ + '.Markup'
+
+
+def _generate_markup_test(impl):
+    def test(gen, el):
+        """<label><x></label>"""
+        gen['markup_wrapper'] = impl
+        return gen.label(contents=impl(u'<x>'))
+
+    wrapper = lambda label: markup_test('xml', schema)(test)()
+    return wrapper