Index: genshi/core.py
===================================================================
--- genshi/core.py	(revision 815)
+++ genshi/core.py	(working copy)
@@ -444,6 +444,9 @@
     def __repr__(self):
         return '<%s %r>' % (self.__class__.__name__, unicode(self))
 
+    def __html__(self):
+        return self
+
     def join(self, seq, escape_quotes=True):
         """Return a `Markup` object which is the concatenation of the strings
         in the given sequence, where this `Markup` object is the separator
@@ -486,6 +489,9 @@
             return cls()
         if type(text) is cls:
             return text
+        if hasattr(text, '__html__'):
+            return Markup(text.__html__())
+
         text = unicode(text).replace('&', '&amp;') \
                             .replace('<', '&lt;') \
                             .replace('>', '&gt;')
Index: genshi/_speedups.c
===================================================================
--- genshi/_speedups.c	(revision 815)
+++ genshi/_speedups.c	(working copy)
@@ -55,6 +55,19 @@
         Py_INCREF(text);
         return text;
     }
+    if (PyObject_HasAttrString(text, "__html__")) {
+        ret = PyObject_CallMethod(text, "__html__", NULL);
+        Py_INCREF(ret);
+        args = PyTuple_New(1);
+        if (args == NULL) {
+            Py_DECREF(ret);
+            return NULL;
+        }
+        PyTuple_SET_ITEM(args, 0, ret);
+        ret = MarkupType.tp_new(&MarkupType, args, NULL);
+        Py_DECREF(args);
+        return ret;
+    }
     in = (PyUnicodeObject *) PyObject_Unicode(text);
     if (in == NULL) {
         return NULL;
@@ -184,6 +197,13 @@
     return self;
 }
 
+static PyObject *
+Markup_html(PyObject *self)
+{
+    Py_INCREF(self);
+    return self;
+}
+
 PyDoc_STRVAR(escape__doc__,
 "Create a Markup instance from a string and escape special characters\n\
 it may contain (<, >, & and \").\n\
@@ -521,6 +541,7 @@
 } MarkupObject;
 
 static PyMethodDef Markup_methods[] = {
+    {"__html__", (PyCFunction) Markup_html, METH_NOARGS, NULL},
     {"escape", (PyCFunction) Markup_escape,
      METH_VARARGS|METH_CLASS|METH_KEYWORDS, escape__doc__},
     {"join", (PyCFunction)Markup_join, METH_VARARGS|METH_KEYWORDS, join__doc__},
