[Zope3-checkins] CVS: Zope3/src/zope/proxy/context - decorator.c:1.7 wrapper.c:1.15

Marius Gedminas mgedmin@codeworks.lt
Mon, 12 May 2003 11:45:11 -0400


Update of /cvs-repository/Zope3/src/zope/proxy/context
In directory cvs.zope.org:/tmp/cvs-serv21280/src/zope/proxy/context

Modified Files:
	decorator.c wrapper.c 
Log Message:
Applied the recent descriptor.c fixes to wrapper.c:
- Access to descriptor->ob_type->tp_descr_get and tp_descr_set is now only done
  when PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) is true.
- The name argument of getattro/setattro wrappers is converted from Unicode
  when necessary and it's reference count is incremented temporarily to prevent
  it from being GCed at the wrong time.


=== Zope3/src/zope/proxy/context/decorator.c 1.6 => 1.7 ===
--- Zope3/src/zope/proxy/context/decorator.c:1.6	Mon May 12 10:59:36 2003
+++ Zope3/src/zope/proxy/context/decorator.c	Mon May 12 11:44:40 2003
@@ -338,11 +338,6 @@
         } \
     }
 
-/* XXX Port improvements / fixes to wrapper.c
- *   * port string ref changes in getattro and setattro to wrapper.c
- *   * port PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS) guarding
- *     use of descriptor->ob_type->tp_descr_{get,set}
- */
 static PyObject *
 decorate_getattro(PyObject *self, PyObject *name)
 {


=== Zope3/src/zope/proxy/context/wrapper.c 1.14 => 1.15 ===
--- Zope3/src/zope/proxy/context/wrapper.c:1.14	Mon May 12 04:50:38 2003
+++ Zope3/src/zope/proxy/context/wrapper.c	Mon May 12 11:44:40 2003
@@ -640,16 +640,36 @@
     PyObject *wrapped;
     PyObject *descriptor;
     PyObject *wrapped_type;
+    PyObject *res = NULL;
+
+#ifdef Py_USING_UNICODE
+    /* The Unicode to string conversion is done here because the
+       existing tp_getattro slots expect a string object as name
+       and we wouldn't want to break those. */
+    if (PyUnicode_Check(name)) {
+        name = PyUnicode_AsEncodedString(name, NULL, NULL);
+        if (name == NULL)
+            return NULL;
+    }
+    else
+#endif
+    if (!PyString_Check(name)){
+        PyErr_SetString(PyExc_TypeError, "attribute name must be string");
+        return NULL;
+    }
+    else
+        Py_INCREF(name);
 
     wrapped = Proxy_GET_OBJECT(self);
     if (wrapped == NULL) {
         PyErr_Format(PyExc_RuntimeError,
             "object is NULL; requested to get attribute '%s'",
             PyString_AS_STRING(name));
-        return NULL;
+        goto finally;
     }
     descriptor = _PyType_Lookup(wrapped->ob_type, name);
     if (descriptor != NULL &&
+        PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) &&
         descriptor->ob_type->tp_descr_get != NULL &&
         (PyObject_TypeCheck(descriptor, &ContextDescriptorType) ||
         /* If object is context-aware, still don't rebind __class__.
@@ -660,13 +680,17 @@
         )) {
         wrapped_type = (PyObject *)wrapped->ob_type;
         if (wrapped_type == NULL)
-            return NULL;
-        return descriptor->ob_type->tp_descr_get(
+            goto finally;
+        res = descriptor->ob_type->tp_descr_get(
                 descriptor,
                 self,
                 wrapped_type);
+        goto finally;
     }
-    return PyObject_GetAttr(wrapped, name);
+    res = PyObject_GetAttr(wrapped, name);
+finally:
+    Py_DECREF(name);
+    return res;
 }
 
 static int
@@ -674,22 +698,46 @@
 {
     PyObject *wrapped;
     PyObject *descriptor;
+    int res = -1;
+
+#ifdef Py_USING_UNICODE
+    /* The Unicode to string conversion is done here because the
+       existing tp_setattro slots expect a string object as name
+       and we wouldn't want to break those. */
+    if (PyUnicode_Check(name)) {
+        name = PyUnicode_AsEncodedString(name, NULL, NULL);
+        if (name == NULL)
+            return -1;
+    }
+    else
+#endif
+    if (!PyString_Check(name)){
+        PyErr_SetString(PyExc_TypeError, "attribute name must be string");
+        return -1;
+    }
+    else
+        Py_INCREF(name);
 
     wrapped = Proxy_GET_OBJECT(self);
     if (wrapped == NULL) {
         PyErr_Format(PyExc_RuntimeError,
             "object is NULL; requested to set attribute '%s'",
             PyString_AS_STRING(name));
-        return -1;
+        goto finally;
     }
     descriptor = _PyType_Lookup(wrapped->ob_type, name);
     if (descriptor != NULL &&
+        PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) &&
         (PyObject_TypeCheck(descriptor, &ContextDescriptorType) ||
          PyObject_TypeCheck(wrapped, &ContextAwareType)) &&
         descriptor->ob_type->tp_descr_set != NULL
         )
-        return descriptor->ob_type->tp_descr_set(descriptor, self, value);
-    return PyObject_SetAttr(wrapped, name, value);
+        res = descriptor->ob_type->tp_descr_set(descriptor, self, value);
+    else
+        res = PyObject_SetAttr(wrapped, name, value);
+finally:
+    Py_DECREF(name);
+    return res;
 }
 
 /* What follows are specific implementations of tp_-slots for those slots
@@ -709,6 +757,7 @@
 
 #define FILLSLOTIF(BADVAL) \
     if (descriptor != NULL && \
+        PyType_HasFeature(descriptor->ob_type, Py_TPFLAGS_HAVE_CLASS) && \
         descriptor->ob_type->tp_descr_get != NULL && \
         (PyObject_TypeCheck(descriptor, &ContextDescriptorType) || \
             PyObject_TypeCheck(wrapped, &ContextAwareType))\