durusmail: quixote-users: Inconsistency between _c_htmltext.c and _py_htmltext.py
Inconsistency between _c_htmltext.c and _py_htmltext.py
2004-03-08
Inconsistency between _c_htmltext.c and_py_htmltext.py
2004-03-08
Inconsistency between _c_htmltext.c and_py_htmltext.py
2004-03-08
Inconsistency between _c_htmltext.c and _py_htmltext.py
Neil Schemenauer
2004-03-08
On Sun, Mar 07, 2004 at 07:15:28PM -0600, Jason Sibre wrote:
> The problem is that an instance of htmltext that came from the c version
> will not accept a mapping object other than a dict, or a subclass of one,
> while the python version of htmltext will allow you to provide any
> 'mapping-like' object.

This is a known bug that I haven't got around to fixing yet.  I'm
sorry you had to discover it yourself.  I've just whipped up a patch
that I think fixes the problem in an elegant way.  See the
attachment.

  Neil


Index: src/_c_htmltext.c
===================================================================
--- src/_c_htmltext.c   (revision 23644)
+++ src/_c_htmltext.c   (working copy)
@@ -23,8 +23,19 @@

 #define QuoteWrapper_Check(v)  ((v)->ob_type == &QuoteWrapper_Type)

+
 typedef struct {
        PyObject_HEAD
+       PyObject *obj;
+} DictWrapperObject;
+
+static PyTypeObject DictWrapper_Type;
+
+#define DictWrapper_Check(v)   ((v)->ob_type == &DictWrapper_Type)
+
+
+typedef struct {
+       PyObject_HEAD
        int html;
        char *buf;
        size_t size;
@@ -179,6 +190,38 @@
 }

 static PyObject *
+dict_wrapper_new(PyObject *o)
+{
+       DictWrapperObject *self;
+       self = PyObject_New(DictWrapperObject, &DictWrapper_Type);
+       if (self == NULL)
+               return NULL;
+       Py_INCREF(o);
+       self->obj = o;
+       return (PyObject *)self;
+}
+
+static void
+dict_wrapper_dealloc(DictWrapperObject *self)
+{
+       Py_DECREF(self->obj);
+       PyObject_Del(self);
+}
+
+static PyObject *
+dict_wrapper_subscript(DictWrapperObject *self, PyObject *key)
+{
+       PyObject *v, *w;;
+       v = PyObject_GetItem(self->obj, key);
+       if (v == NULL) {
+               return NULL;
+       }
+       w = quote_wrapper_new(v);
+       Py_DECREF(v);
+       return w;
+}
+
+static PyObject *
 htmltext_from_string(PyObject *s)
 {
        /* note, this takes a reference */
@@ -316,21 +359,9 @@
                }
        }
        if (do_dict) {
-               int pos = 0;
-               PyObject *key, *value;
-               wargs = PyDict_New();
-               while (PyDict_Next(args, &pos, &key, &value)) {
-                       PyObject *wvalue = wrap_arg(value);
-                       if (wvalue == NULL) {
-                               Py_DECREF(wargs);
-                               return NULL;
-                       }
-                       if (PyDict_SetItem(wargs, key, wvalue) < 0) {
-                               Py_DECREF(wargs);
-                               return NULL;
-                       }
-                       Py_DECREF(wvalue);
-               }
+               wargs = dict_wrapper_new(args);
+               if (wargs == NULL)
+                       return NULL;
        }
        else if (PyTuple_Check(args)) {
                long i, n = PyTuple_GET_SIZE(args);
@@ -808,6 +839,30 @@
        (unaryfunc)quote_wrapper_str,  /*tp_str*/
 };

+static PyMappingMethods dict_wrapper_as_mapping = {
+        0, /*mp_length*/
+        (binaryfunc)dict_wrapper_subscript, /*mp_subscript*/
+        0, /*mp_ass_subscript*/
+};
+
+static PyTypeObject DictWrapper_Type = {
+       PyObject_HEAD_INIT(NULL)
+       0,                      /*ob_size*/
+       "DictWrapper",          /*tp_name*/
+       sizeof(DictWrapperObject),      /*tp_basicsize*/
+       0,                      /*tp_itemsize*/
+       /* methods */
+       (destructor)dict_wrapper_dealloc, /*tp_dealloc*/
+       0,                      /*tp_print*/
+       0,                      /*tp_getattr*/
+       0,                      /*tp_setattr*/
+       0,                      /*tp_compare*/
+       0,                      /*tp_repr*/
+       0,                      /*tp_as_number*/
+       0,                      /*tp_as_sequence*/
+       &dict_wrapper_as_mapping,/*tp_as_mapping*/
+};
+
 static PyNumberMethods template_io_as_number = {
        0, /*nb_add*/
        0, /*nb_subtract*/
Index: _py_htmltext.py
===================================================================
--- _py_htmltext.py     (revision 23644)
+++ _py_htmltext.py     (working copy)
@@ -72,24 +72,18 @@
     def __mod__(self, args):
         codes = []
         usedict = 0
-        klass = self.__class__
         for format in _format_re.findall(self.s):
             if format[-1] != '%':
                 if format[1] == '(':
                     usedict = 1
                 codes.append(format[-1])
         if usedict:
-            if not hasattr(args, "items"):
-                raise TypeError, "mapping required"
-            wrapped_args = {}
-            for (k, v) in args.items():
-                wrapped_args[k] = _wraparg(klass, v)
-            args = wrapped_args
+            args = _DictWrapper(args)
         else:
             if len(codes) == 1 and not isinstance(args, TupleType):
                 args = (args,)
-            args = tuple([_wraparg(klass, arg) for arg in args])
-        return klass(self.s % args)
+            args = tuple([_wraparg(arg) for arg in args])
+        return self.__class__(self.s % args)

     def __add__(self, other):
         if isinstance(other, StringType):
@@ -169,8 +163,15 @@
     def __repr__(self):
         return self.escape(`self.value`)

-def _wraparg(klass, arg):
-    if (classof(arg) is klass or
+class _DictWrapper(object):
+    def __init__(self, value):
+        self.value = value
+
+    def __getitem__(self, key):
+        return _wraparg(self.value[key])
+
+def _wraparg(arg):
+    if (classof(arg) is htmltext or
         isinstance(arg, IntType) or
         isinstance(arg, LongType) or
         isinstance(arg, FloatType)):


reply